home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Utilities / vim-5.1 / src / edit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-23  |  118.4 KB  |  4,989 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8.  
  9. /*
  10.  * edit.c: functions for Insert mode
  11.  */
  12.  
  13. #include "vim.h"
  14.  
  15. #ifdef INSERT_EXPAND
  16. /*
  17.  * definitions used for CTRL-X submode
  18.  */
  19. #define CTRL_X_WANT_IDENT    0x100
  20.  
  21. #define CTRL_X_NOT_DEFINED_YET    (1)
  22. #define CTRL_X_SCROLL        (2)
  23. #define CTRL_X_WHOLE_LINE    (3)
  24. #define CTRL_X_FILES        (4)
  25. #define CTRL_X_TAGS        (5 + CTRL_X_WANT_IDENT)
  26. #define CTRL_X_PATH_PATTERNS    (6 + CTRL_X_WANT_IDENT)
  27. #define CTRL_X_PATH_DEFINES    (7 + CTRL_X_WANT_IDENT)
  28. #define CTRL_X_FINISHED        (8)
  29. #define CTRL_X_DICTIONARY    (9 + CTRL_X_WANT_IDENT)
  30.  
  31. #define C_X_SKIP        (7) /* length of " Adding" */
  32. char *ctrl_x_msgs[] =
  33. {
  34.     " Adding Keyword completion (^N/^P)", /* ctrl_x_mode == 0, ^P/^N compl. */
  35.     " ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^N/^P)",
  36.     /* Scroll has it's own msgs, in it's place there is the msg for local
  37.      * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL)  -- Acevedo */
  38.     " Adding Keyword Local completion (^N/^P)",
  39.     " Adding Whole line completion (^L/^N/^P)",
  40.     " Adding File name completion (^F/^N/^P)",
  41.     " Adding Tag completion (^]/^N/^P)",
  42.     " Adding Path pattern completion (^N/^P)",
  43.     " Adding Definition completion (^D/^N/^P)",
  44.     NULL,
  45.     " Adding Dictionary completion (^K/^N/^P)"
  46. };
  47.  
  48. char_u e_hitend[] = "Hit end of paragraph";
  49. char_u e_hitend_f[] = "Hit end of paragraph (forward)";
  50. char_u e_hitend_b[] = "Hit end of paragraph (backward)";
  51. char_u e_patnotf_f[] = "Pattern not found (forward)";
  52. char_u e_patnotf_b[] = "Pattern not found (backward)";
  53.  
  54. /*
  55.  * Structure used to store one match for insert completion.
  56.  */
  57. struct Completion
  58. {
  59.     struct Completion    *next;
  60.     struct Completion    *prev;
  61.     char_u        *str;      /* matched text */
  62.     char_u        *fname;      /* file containing the match */
  63.     int            original; /* ORIGINAL_TEXT, CONT_S_IPOS or FREE_FNAME */
  64. };
  65.  
  66. /* the original text when the expansion begun */
  67. #define ORIGINAL_TEXT    (1)
  68. #define FREE_FNAME    (2)
  69. /*
  70.  * All the current matches are stored in a list.
  71.  * "first_match" points to the start of the list.
  72.  * "curr_match" points to the currently selected entry.
  73.  */
  74. static struct Completion    *first_match = NULL;
  75. static struct Completion    *curr_match = NULL;
  76. static int            started_completion;
  77. static char_u            *complete_pat;
  78. static int            save_sm;
  79. static char_u            *original_text = NULL;  /* text before completion */
  80. static int            continue_mode = 0;
  81.  
  82. static int  add_completion __ARGS((char_u *str, int len, char_u *, int dir, int reuse));
  83. static int  make_cyclic __ARGS((void));
  84. static void complete_dictionaries __ARGS((char_u *dict, char_u *pat, int dir, int flags));
  85. static void free_completions __ARGS((void));
  86. static void clear_insexp __ARGS((void));
  87. static int  ins_expand_pre __ARGS((int c));
  88. static BUF  *next_buf __ARGS((BUF *buf, int flag));
  89. static int  get_expansion __ARGS((FPOS *ini, int dir));
  90. static int  ins_complete __ARGS((int c));
  91. static int  quote_meta __ARGS((char_u *dest, char_u *str, int len));
  92. #endif /* INSERT_EXPAND */
  93.  
  94. #define BACKSPACE_CHAR            1
  95. #define BACKSPACE_WORD            2
  96. #define BACKSPACE_WORD_NOT_SPACE    3
  97. #define BACKSPACE_LINE            4
  98.  
  99. static void edit_putchar __ARGS((int c, int highlight));
  100. static void undisplay_dollar __ARGS((void));
  101. static void change_indent __ARGS((int type, int amount, int round, int replaced));
  102. static void insert_special __ARGS((int, int, int));
  103. static void redo_literal __ARGS((int c));
  104. static void start_arrow __ARGS((FPOS *end_insert_pos));
  105. static void stop_insert __ARGS((FPOS *end_insert_pos));
  106. static int  echeck_abbr __ARGS((int));
  107. static void replace_push_off __ARGS((int c));
  108. static int  replace_pop __ARGS((void));
  109. static void replace_join __ARGS((int off));
  110. static void replace_pop_ins __ARGS((void));
  111. static void replace_flush __ARGS((void));
  112. static void replace_do_bs __ARGS((void));
  113. static int  ins_reg __ARGS((void));
  114. static int  ins_esc __ARGS((long *count, int need_redraw, int cmdchar));
  115. #ifdef RIGHTLEFT
  116. static void ins_ctrl_ __ARGS((void));
  117. #endif
  118. static void ins_shift __ARGS((int c, int lastc));
  119. static void ins_del __ARGS((void));
  120. static int  ins_bs __ARGS((int c, int mode, int *inserted_space_p));
  121. #ifdef USE_MOUSE
  122. static void ins_mouse __ARGS((int c));
  123. #endif
  124. static void ins_left __ARGS((void));
  125. static void ins_home __ARGS((void));
  126. static void ins_end __ARGS((void));
  127. static void ins_s_left __ARGS((void));
  128. static void ins_right __ARGS((void));
  129. static void ins_s_right __ARGS((void));
  130. static void ins_up __ARGS((void));
  131. static void ins_pageup __ARGS((void));
  132. static void ins_down __ARGS((void));
  133. static void ins_pagedown __ARGS((void));
  134. static int  ins_tab __ARGS((void));
  135. static int  ins_eol __ARGS((int c));
  136. #ifdef DIGRAPHS
  137. static int  ins_digraph __ARGS((void));
  138. #endif
  139. static int  ins_copychar __ARGS((linenr_t lnum));
  140. #ifdef SMARTINDENT
  141. static void ins_try_si __ARGS((int c));
  142. #endif
  143. static colnr_t get_nolist_virtcol __ARGS((void));
  144.  
  145. static FPOS    Insstart;        /* This is where the latest
  146.                      * insert/append mode started. */
  147. static colnr_t    Insstart_textlen;    /* length of line when insert started */
  148. static colnr_t    Insstart_blank_vcol;    /* vcol for first inserted blank */
  149.  
  150. static char_u    *last_insert = NULL;    /* the text of the previous insert */
  151. static int    last_insert_skip; /* nr of chars in front of previous insert */
  152. static int    new_insert_skip;  /* nr of chars in front of current insert */
  153.  
  154. #ifdef CINDENT
  155. static int    can_cindent;        /* may do cindenting on this line */
  156. #endif
  157.  
  158. static int    old_indent = 0;        /* for ^^D command in insert mode */
  159.  
  160. #ifdef RIGHTLEFT
  161. int        revins_on;            /* reverse insert mode on */
  162. int        revins_chars;        /* how much to skip after edit */
  163. int        revins_legal;        /* was the last char 'legal'? */
  164. int        revins_scol;        /* start column of revins session */
  165. #endif
  166.  
  167. /*
  168.  * edit(): Start insering text.
  169.  *
  170.  * "cmdchar" can be:
  171.  * 'i'    normal insert command
  172.  * 'a'    normal append command
  173.  * 'R'    replace command
  174.  * 'r'    "r<CR>" command: insert one <CR>.  Note: count can be > 1, for redo,
  175.  *    but still only one <CR> is inserted.  The <Esc> is not used for redo.
  176.  * 'g'    "gI" command.
  177.  *
  178.  * This function is not called recursively.  For CTRL-O commands, it returns
  179.  * and lets the caller handle the Normal-mode command.
  180.  *
  181.  * Return TRUE if a CTRL-O command caused the return (insert mode pending).
  182.  */
  183.     int
  184. edit(cmdchar, startln, count)
  185.     int        cmdchar;
  186.     int        startln;    /* if set, insert at start of line */
  187.     long    count;
  188. {
  189.     int         c = 0;
  190.     char_u    *ptr;
  191.     int         lastc;
  192.     colnr_t     mincol;
  193.     static linenr_t o_lnum = 0;
  194.     static int     o_eol = FALSE;
  195.     int         need_redraw = FALSE;
  196.     int         i;
  197.     int         did_backspace = TRUE;        /* previous char was backspace */
  198. #ifdef CINDENT
  199.     int         line_is_white = FALSE;        /* line is empty before insert */
  200. #endif
  201.     linenr_t     old_topline = 0;        /* topline before insertion */
  202.     int         inserted_space = FALSE;    /* just inserted a space */
  203.  
  204.     /* sleep before redrawing, needed for "CTRL-O :" that results in an
  205.      * error message */
  206.     check_for_delay(TRUE);
  207.  
  208. #ifdef INSERT_EXPAND
  209.     clear_insexp();        /* clear stuff for ctrl-x mode */
  210. #endif
  211.  
  212. #ifdef USE_MOUSE
  213.     /*
  214.      * When doing a paste with the middle mouse button, Insstart is set to
  215.      * where the paste started.
  216.      */
  217.     if (where_paste_started.lnum != 0)
  218.     Insstart = where_paste_started;
  219.     else
  220. #endif
  221.     {
  222.     Insstart = curwin->w_cursor;
  223.     if (startln)
  224.         Insstart.col = 0;
  225.     }
  226.     Insstart_textlen = linetabsize(ml_get_curline());
  227.     Insstart_blank_vcol = MAXCOL;
  228.  
  229.     if (cmdchar != NUL && !restart_edit)
  230.     {
  231.     ResetRedobuff();
  232.     AppendNumberToRedobuff(count);
  233.     AppendCharToRedobuff(cmdchar);
  234.     if (cmdchar == 'g')            /* "gI" command */
  235.         AppendCharToRedobuff('I');
  236.     else if (cmdchar == 'r')        /* "r<CR>" command */
  237.         count = 1;                /* insert only one <CR> */
  238.     }
  239.  
  240.     if (cmdchar == 'R')
  241.     {
  242. #ifdef FKMAP
  243.     if (p_fkmap && p_ri)
  244.     {
  245.         beep_flush();
  246.         EMSG(farsi_text_3);        /* encoded in Farsi */
  247.         State = INSERT;
  248.     }
  249.     else
  250. #endif
  251.     State = REPLACE;
  252.     }
  253.     else
  254.     State = INSERT;
  255.     /*
  256.      * Need to recompute the cursor position, it might move when the cursor is
  257.      * on a TAB or special character.
  258.      */
  259.     curs_columns(TRUE);
  260.  
  261. #ifdef USE_MOUSE
  262.     setmouse();
  263. #endif
  264. #ifdef SHOWCMD
  265.     clear_showcmd();
  266. #endif
  267. #ifdef RIGHTLEFT
  268.     /* there is no reverse replace mode */
  269.     revins_on = (State == INSERT && p_ri);
  270.     if (revins_on)
  271.     undisplay_dollar();
  272.     revins_chars = 0;
  273.     revins_legal = 0;
  274.     revins_scol = -1;
  275. #endif
  276.  
  277.     /*
  278.      * Handle restarting Insert mode.
  279.      * Don't do this for CTRL-O . (repeat an insert): we get here with
  280.      * restart_edit non-zero, and something in the stuff buffer.
  281.      */
  282.     if (restart_edit && stuff_empty())
  283.     {
  284. #ifdef USE_MOUSE
  285.     /*
  286.      * After a paste we consider text typed to be part of the insert for
  287.      * the pasted text. You can backspace over the paste text too.
  288.      */
  289.     if (where_paste_started.lnum)
  290.         arrow_used = FALSE;
  291.     else
  292. #endif
  293.         arrow_used = TRUE;
  294.     restart_edit = 0;
  295.  
  296.     /*
  297.      * If the cursor was after the end-of-line before the CTRL-O and it is
  298.      * now at the end-of-line, put it after the end-of-line (this is not
  299.      * correct in very rare cases).
  300.      * Also do this if curswant is greater than the current virtual
  301.      * column.  Eg after "^O$" or "^O80|".
  302.      */
  303.     validate_virtcol();
  304.     update_curswant();
  305.     if (       ((o_eol && curwin->w_cursor.lnum == o_lnum)
  306.             || curwin->w_curswant > curwin->w_virtcol)
  307.         && *(ptr = ml_get_curline() + curwin->w_cursor.col) != NUL
  308.         && *(ptr + 1) == NUL)
  309.         ++curwin->w_cursor.col;
  310.     }
  311.     else
  312.     {
  313.     arrow_used = FALSE;
  314.     o_eol = FALSE;
  315.     }
  316. #ifdef USE_MOUSE
  317.     where_paste_started.lnum = 0;
  318. #endif
  319. #ifdef CINDENT
  320.     can_cindent = TRUE;
  321. #endif
  322.  
  323.     /*
  324.      * If 'showmode' is set, show the current (insert/replace/..) mode.
  325.      * A warning message for changing a readonly file is given here, before
  326.      * actually changing anything.  It's put after the mode, if any.
  327.      */
  328.     i = 0;
  329.     if (p_smd)
  330.     i = showmode();
  331.  
  332.     if (!p_im)
  333.     change_warning(i + 1);
  334.  
  335. #ifdef USE_GUI
  336.     if (gui.in_use)
  337.     gui_upd_cursor_shape();        /* may show different cursor shape */
  338. #endif
  339. #ifdef DIGRAPHS
  340.     do_digraph(-1);            /* clear digraphs */
  341. #endif
  342.  
  343. /*
  344.  * Get the current length of the redo buffer, those characters have to be
  345.  * skipped if we want to get to the inserted characters.
  346.  */
  347.     ptr = get_inserted();
  348.     if (ptr == NULL)
  349.     new_insert_skip = 0;
  350.     else
  351.     {
  352.     new_insert_skip = STRLEN(ptr);
  353.     vim_free(ptr);
  354.     }
  355.  
  356.     old_indent = 0;
  357.  
  358.     for (;;)
  359.     {
  360. #ifdef RIGHTLEFT
  361.     if (!revins_legal)
  362.         revins_scol = -1;        /* reset on illegal motions */
  363.     else
  364.         revins_legal = 0;
  365. #endif
  366.     if (arrow_used)        /* don't repeat insert when arrow key used */
  367.         count = 0;
  368.  
  369.         /* set curwin->w_curswant for next K_DOWN or K_UP */
  370.     if (!arrow_used)
  371.         curwin->w_set_curswant = TRUE;
  372.  
  373.     /*
  374.      * When emsg() was called msg_scroll will have been set.
  375.      */
  376.     msg_scroll = FALSE;
  377.  
  378.     /*
  379.      * If we inserted a character at the last position of the last line in
  380.      * the window, scroll the window one line up. This avoids an extra
  381.      * redraw.
  382.      * This is detected when the cursor column is smaller after inserting
  383.      * something.
  384.      * Don't do this when the topline changed already, it has
  385.      * already been adjusted (by insertchar() calling open_line())).
  386.      */
  387.     if (need_redraw && curwin->w_p_wrap && !did_backspace &&
  388.                          curwin->w_topline == old_topline)
  389.     {
  390.         mincol = curwin->w_wcol;
  391.         validate_cursor_col();
  392.  
  393.         if ((int)curwin->w_wcol < (int)mincol - curbuf->b_p_ts &&
  394.             curwin->w_wrow == curwin->w_winpos +
  395.                         curwin->w_height - 1 - p_so &&
  396.             curwin->w_cursor.lnum != curwin->w_topline)
  397.         {
  398.         set_topline(curwin, curwin->w_topline + 1);
  399.         update_topline();
  400.         update_screen(VALID_TO_CURSCHAR);
  401.         need_redraw = FALSE;
  402.         }
  403.         else
  404.         update_topline();
  405.     }
  406.     else
  407.         update_topline();
  408.     did_backspace = FALSE;
  409.  
  410.     /*
  411.      * redraw is postponed until here to make 'dollar' option work
  412.      * correctly.
  413.      */
  414.     validate_cursor();        /* may set must_redraw */
  415.     if (need_redraw || must_redraw)
  416.     {
  417.         update_screenline();
  418.         if (curwin->w_redr_status == TRUE)
  419.         win_redr_status(curwin);    /* display [+] if required */
  420.         need_redraw = FALSE;
  421.     }
  422.     else if (clear_cmdline || redraw_cmdline)
  423.         showmode();            /* clear cmdline, show mode and ruler */
  424.  
  425.     showruler(FALSE);
  426.     setcursor();
  427.     update_curswant();
  428.     emsg_on_display = FALSE;    /* may remove error message now */
  429.     old_topline = curwin->w_topline;
  430.  
  431. #ifdef USE_GUI_WIN32
  432.     dont_scroll = FALSE;        /* allow scrolling here */
  433. #endif
  434.     lastc = c;            /* remember previous char for CTRL-D */
  435.     c = vgetc();
  436.  
  437. #ifdef RIGHTLEFT
  438.     if (p_hkmap && KeyTyped)
  439.         c = hkmap(c);        /* Hebrew mode mapping */
  440. #endif
  441. #ifdef FKMAP
  442.     if (p_fkmap && KeyTyped)
  443.         c = fkmap(c);        /* Farsi mode mapping */
  444. #endif
  445.  
  446. #ifdef INSERT_EXPAND
  447.     /*
  448.      * Prepare for or stop ctrl-x mode.
  449.      */
  450.     need_redraw |= ins_expand_pre(c);
  451. #endif
  452.  
  453. #ifdef DIGRAPHS
  454.     c = do_digraph(c);
  455. #endif
  456.  
  457.     if (c == Ctrl('V') || c == Ctrl('Q'))
  458.     {
  459.         if (redrawing() && !char_avail())
  460.         edit_putchar('^', TRUE);
  461.         AppendToRedobuff((char_u *)"\026");    /* CTRL-V */
  462.  
  463. #ifdef SHOWCMD
  464.         add_to_showcmd_c(c);
  465. #endif
  466.  
  467.         c = get_literal();
  468. #ifdef SHOWCMD
  469.         clear_showcmd();
  470. #endif
  471.         insert_special(c, TRUE, TRUE);
  472.         need_redraw = TRUE;
  473. #ifdef RIGHTLEFT
  474.         revins_chars++;
  475.         revins_legal++;
  476. #endif
  477.         c = Ctrl('V');    /* pretend CTRL-V is last typed character */
  478.         continue;
  479.     }
  480.  
  481. #ifdef CINDENT
  482.     if (curbuf->b_p_cin
  483. # ifdef INSERT_EXPAND
  484.                 && !ctrl_x_mode
  485. # endif
  486.                            )
  487.     {
  488.         line_is_white = inindent(0);
  489.  
  490.         /*
  491.          * A key name preceded by a bang means that this
  492.          * key wasn't destined to be inserted.  Skip ahead
  493.          * to the re-indenting if we find one.
  494.          */
  495.         if (in_cinkeys(c, '!', line_is_white))
  496.         goto force_cindent;
  497.  
  498.         /*
  499.          * A key name preceded by a star means that indenting
  500.          * has to be done before inserting the key.
  501.          */
  502.         if (can_cindent && in_cinkeys(c, '*', line_is_white))
  503.         {
  504.         stop_arrow();
  505.  
  506.         /* re-indent the current line */
  507.         fixthisline(get_c_indent);
  508.  
  509.         /* draw the changes on the screen later */
  510.         need_redraw = TRUE;
  511.         }
  512.     }
  513. #endif /* CINDENT */
  514.  
  515. #ifdef RIGHTLEFT
  516.     if (curwin->w_p_rl)
  517.         switch (c)
  518.         {
  519.         case K_LEFT:    c = K_RIGHT; break;
  520.         case K_S_LEFT:    c = K_S_RIGHT; break;
  521.         case K_RIGHT:    c = K_LEFT; break;
  522.         case K_S_RIGHT: c = K_S_LEFT; break;
  523.         }
  524. #endif
  525.  
  526.     /*
  527.      * The big switch to handle a character in insert mode.
  528.      */
  529.     switch (c)
  530.     {
  531.     case K_INS:        /* toggle insert/replace mode */
  532. #ifdef FKMAP
  533.         if (p_fkmap && p_ri)
  534.         {
  535.         beep_flush();
  536.         EMSG(farsi_text_3);    /* encoded in Farsi */
  537.         break;
  538.         }
  539. #endif
  540.         if (State == REPLACE)
  541.         State = INSERT;
  542.         else
  543.         State = REPLACE;
  544.         AppendCharToRedobuff(K_INS);
  545.         showmode();
  546. #ifdef USE_GUI
  547.         if (gui.in_use)
  548.         gui_upd_cursor_shape();    /* may show different cursor shape */
  549. #endif
  550.         break;
  551.  
  552. #ifdef INSERT_EXPAND
  553.     case Ctrl('X'):        /* Enter ctrl-x mode */
  554.         /* if the next ^X<> won't ADD nothing, then reset continue_status */
  555.         continue_status = continue_status & CONT_N_ADDS ?
  556.         continue_status | CONT_INTRPT : 0;
  557.         /* We're not sure which ctrl-x mode it will be yet */
  558.         ctrl_x_mode = CTRL_X_NOT_DEFINED_YET;
  559.         edit_submode = (char_u *)ctrl_x_msgs[ctrl_x_mode & 15];
  560.         showmode();
  561.         break;
  562. #endif
  563.  
  564.     case Ctrl('Z'):        /* suspend when 'insertmode' set */
  565.         if (!p_im)
  566.         goto normalchar;    /* insert CTRL-Z as normal char */
  567.         stuffReadbuff((char_u *)":st\r");
  568.         c = Ctrl('O');
  569.         /*FALLTHROUGH*/
  570.  
  571.     case Ctrl('O'):        /* execute one command */
  572.         if (echeck_abbr(Ctrl('O') + ABBR_OFF))
  573.         break;
  574.         count = 0;
  575.         if (State == INSERT)
  576.         restart_edit = 'I';
  577.         else
  578.         restart_edit = 'R';
  579.         o_lnum = curwin->w_cursor.lnum;
  580.         o_eol = (gchar_cursor() == NUL);
  581.         goto doESCkey;
  582.  
  583. #ifdef USE_SNIFF
  584.     case K_SNIFF:
  585.         stuffcharReadbuff(K_SNIFF);
  586.         goto doESCkey;
  587. #endif
  588.  
  589.       /* Hitting the help key in insert mode is like <ESC> <Help> */
  590.     case K_HELP:
  591.     case K_F1:
  592.         stuffcharReadbuff(K_HELP);
  593.         if (p_im)
  594.         stuffcharReadbuff('i');
  595.         goto doESCkey;
  596.  
  597.     case ESC:        /* an escape ends input mode */
  598.         if (echeck_abbr(ESC + ABBR_OFF))
  599.         break;
  600.         /*FALLTHROUGH*/
  601.  
  602.     case Ctrl('C'):
  603. #ifdef UNIX
  604. do_intr:
  605. #endif
  606.         if (p_im)
  607.         {
  608.         if (got_int)
  609.         {
  610.             (void)vgetc();        /* flush all buffers */
  611.             got_int = FALSE;
  612.         }
  613.         else
  614.             vim_beep();
  615.         break;
  616.         }
  617. doESCkey:
  618.         /*
  619.          * This is the ONLY return from edit()!
  620.          */
  621.         if (ins_esc(&count, need_redraw, cmdchar))
  622.         return (c == Ctrl('O'));
  623.         continue;
  624.  
  625.         /*
  626.          * Insert the previously inserted text.
  627.          * For ^@ the trailing ESC will end the insert, unless there
  628.          * is an error.
  629.          */
  630.     case K_ZERO:
  631.     case NUL:
  632.     case Ctrl('A'):
  633.         if (stuff_inserted(NUL, 1L, (c == Ctrl('A'))) == FAIL
  634.                            && c != Ctrl('A') && !p_im)
  635.         goto doESCkey;        /* quit insert mode */
  636.         break;
  637.  
  638.     /*
  639.      * insert the contents of a register
  640.      */
  641.     case Ctrl('R'):
  642.         need_redraw |= ins_reg();
  643.         break;
  644.  
  645. #ifdef RIGHTLEFT
  646.     /*
  647.      * toggle language: khmap and revins_on
  648.      * Move to end of reverse inserted text.
  649.      */
  650.     case Ctrl('_'):
  651.         ins_ctrl_();
  652.         break;
  653. #endif
  654.  
  655.     /* Make indent one shiftwidth smaller. */
  656.     case Ctrl('D'):
  657. #if defined(INSERT_EXPAND) && defined(FIND_IN_PATH)
  658.         if (ctrl_x_mode == CTRL_X_PATH_DEFINES)
  659.         goto docomplete;
  660. #endif
  661.         /* FALLTHROUGH */
  662.  
  663.     /* Make indent one shiftwidth greater. */
  664.     case Ctrl('T'):
  665.         ins_shift(c, lastc);
  666.         need_redraw = TRUE;
  667.         break;
  668.  
  669.     /* delete character under the cursor */
  670.     case K_DEL:
  671.         ins_del();
  672.         need_redraw = TRUE;
  673.         break;
  674.  
  675.     /* delete character before the cursor */
  676.     case K_BS:
  677.     case Ctrl('H'):
  678.         did_backspace = ins_bs(c, BACKSPACE_CHAR, &inserted_space);
  679.         need_redraw = TRUE;
  680.         break;
  681.  
  682.     /* delete word before the cursor */
  683.     case Ctrl('W'):
  684.         did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space);
  685.         need_redraw = TRUE;
  686.         break;
  687.  
  688.     /* delete all inserted text in current line */
  689.     case Ctrl('U'):
  690.         did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space);
  691.         need_redraw = TRUE;
  692.         break;
  693.  
  694. #ifdef USE_MOUSE
  695.     case K_LEFTMOUSE:
  696.     case K_LEFTDRAG:
  697.     case K_LEFTRELEASE:
  698.     case K_MIDDLEMOUSE:
  699.     case K_MIDDLEDRAG:
  700.     case K_MIDDLERELEASE:
  701.     case K_RIGHTMOUSE:
  702.     case K_RIGHTDRAG:
  703.     case K_RIGHTRELEASE:
  704.         ins_mouse(c);
  705.         break;
  706.  
  707.     case K_IGNORE:
  708.         break;
  709. #endif
  710.  
  711. #ifdef USE_GUI
  712.     case K_SCROLLBAR:
  713.         ins_scroll();
  714.         break;
  715.  
  716.     case K_HORIZ_SCROLLBAR:
  717.         ins_horscroll();
  718.         break;
  719. #endif
  720.  
  721.     case K_HOME:
  722.     case K_KHOME:
  723.         ins_home();
  724.         break;
  725.  
  726.     case K_END:
  727.     case K_KEND:
  728.         ins_end();
  729.         break;
  730.  
  731.     case K_LEFT:
  732.         if (mod_mask & MOD_MASK_CTRL)
  733.         ins_s_left();
  734.         else
  735.         ins_left();
  736.         break;
  737.  
  738.     case K_S_LEFT:
  739.         ins_s_left();
  740.         break;
  741.  
  742.     case K_RIGHT:
  743.         if (mod_mask & MOD_MASK_CTRL)
  744.         ins_s_right();
  745.         else
  746.         ins_right();
  747.         break;
  748.  
  749.     case K_S_RIGHT:
  750.         ins_s_right();
  751.         break;
  752.  
  753.     case K_UP:
  754.         ins_up();
  755.         break;
  756.  
  757.     case K_S_UP:
  758.     case K_PAGEUP:
  759.     case K_KPAGEUP:
  760.         ins_pageup();
  761.         break;
  762.  
  763.     case K_DOWN:
  764.         ins_down();
  765.         break;
  766.  
  767.     case K_S_DOWN:
  768.     case K_PAGEDOWN:
  769.     case K_KPAGEDOWN:
  770.         ins_pagedown();
  771.         break;
  772.  
  773.         /* When <S-Tab> isn't mapped, use it like a normal TAB */
  774.     case K_S_TAB:
  775.         c = TAB;
  776.         /* FALLTHROUGH */
  777.  
  778.     /* TAB or Complete patterns along path */
  779.     case TAB:
  780. #if defined(INSERT_EXPAND) && defined(FIND_IN_PATH)
  781.         if (ctrl_x_mode == CTRL_X_PATH_PATTERNS)
  782.         goto docomplete;
  783. #endif
  784.         inserted_space = FALSE;
  785.         if (ins_tab())
  786.         goto normalchar;    /* insert TAB as a normal char */
  787.         need_redraw = TRUE;
  788.         break;
  789.  
  790.     case CR:
  791.     case NL:
  792.         if (ins_eol(c) && !p_im)
  793.         goto doESCkey;        /* out of memory */
  794.         break;
  795.  
  796. #if defined(DIGRAPHS) || defined (INSERT_EXPAND)
  797.     case Ctrl('K'):
  798. # ifdef INSERT_EXPAND
  799.         if (ctrl_x_mode == CTRL_X_DICTIONARY)
  800.         {
  801.         if (*p_dict == NUL)
  802.         {
  803.             ctrl_x_mode = 0;
  804.             msg_attr((char_u *)"'dictionary' option is empty",
  805.                  highlight_attr[HLF_E]);
  806.             vim_beep();
  807.             setcursor();
  808.             out_flush();
  809.             ui_delay(2000L, FALSE);
  810.             break;
  811.         }
  812.         goto docomplete;
  813.         }
  814. # endif
  815. # ifdef DIGRAPHS
  816.         c = ins_digraph();
  817.         if (c == NUL)
  818.         {
  819.         need_redraw = TRUE;
  820.         break;
  821.         }
  822. # endif
  823.         goto normalchar;
  824. #endif /* DIGRAPHS || INSERT_EXPAND */
  825.  
  826. #ifdef INSERT_EXPAND
  827.     case Ctrl(']'):        /* Tag name completion after ^X */
  828.         if (ctrl_x_mode != CTRL_X_TAGS)
  829.         goto normalchar;
  830.         goto docomplete;
  831.  
  832.     case Ctrl('F'):        /* File name completion after ^X */
  833.         if (ctrl_x_mode != CTRL_X_FILES)
  834.         goto normalchar;
  835.         goto docomplete;
  836. #endif
  837.  
  838.     case Ctrl('L'):        /* Whole line completion after ^X */
  839. #ifdef INSERT_EXPAND
  840.         if (ctrl_x_mode != CTRL_X_WHOLE_LINE)
  841. #endif
  842.         {
  843.         /* CTRL-L with 'insertmode' set: Leave Insert mode */
  844.         if (p_im)
  845.         {
  846.             if (echeck_abbr(Ctrl('L') + ABBR_OFF))
  847.             break;
  848.             goto doESCkey;
  849.         }
  850.         goto normalchar;
  851.         }
  852. #ifdef INSERT_EXPAND
  853.         /* FALLTHROUGH */
  854.  
  855.     case Ctrl('P'):        /* Do previous pattern completion */
  856.     case Ctrl('N'):        /* Do next pattern completion */
  857.         /* if 'complete' is empty then plain ^P is no longer special,
  858.          * but it is under other ^X modes */
  859.         if (    *curbuf->b_p_cpt == NUL && !ctrl_x_mode
  860.             && !(continue_status & CONT_LOCAL))
  861.         goto normalchar;
  862. docomplete:
  863.         i = ins_complete(c);
  864.         if (i)
  865.         need_redraw |= i;
  866.         else
  867.         continue_status = 0;
  868.         break;
  869. #endif /* INSERT_EXPAND */
  870.  
  871.     case Ctrl('Y'):        /* copy from previous line or scroll down */
  872.     case Ctrl('E'):        /* copy from next line       or scroll up */
  873. #ifdef INSERT_EXPAND
  874.         if (ctrl_x_mode == CTRL_X_SCROLL)
  875.         {
  876.         if (c == Ctrl('Y'))
  877.             scrolldown_clamp();
  878.         else
  879.             scrollup_clamp();
  880.         update_screen(VALID);
  881.         }
  882.         else
  883. #endif
  884.         {
  885.         c = ins_copychar(curwin->w_cursor.lnum
  886.                          + (c == Ctrl('Y') ? -1 : 1));
  887.         if (c != NUL)
  888.         {
  889.             long    tw_save;
  890.  
  891.             /* The character must be taken literally, insert like it
  892.              * was typed after a CTRL-V, and pretend 'textwidth'
  893.              * wasn't set */
  894.             AppendToRedobuff((char_u *)"\026");    /* CTRL-V */
  895.             tw_save = curbuf->b_p_tw;
  896.             curbuf->b_p_tw = -1;
  897.             insert_special(c, TRUE, TRUE);
  898.             curbuf->b_p_tw = tw_save;
  899.             need_redraw = TRUE;
  900. #ifdef RIGHTLEFT
  901.             revins_chars++;
  902.             revins_legal++;
  903. #endif
  904.             c = Ctrl('V');    /* pretend CTRL-V is last character */
  905.         }
  906.         }
  907.         break;
  908.  
  909.       default:
  910. #ifdef UNIX
  911.         if (c == intr_char)        /* special interrupt char */
  912.         goto do_intr;
  913. #endif
  914.  
  915. normalchar:
  916. #ifdef SMARTINDENT
  917.         /*
  918.          * Try to perform smart-indenting.
  919.          */
  920.         ins_try_si(c);
  921. #endif
  922.  
  923.         if (c == ' ')
  924.         {
  925.         inserted_space = TRUE;
  926. #ifdef CINDENT
  927.         if (inindent(0))
  928.             can_cindent = FALSE;
  929. #endif
  930.         if (Insstart_blank_vcol == MAXCOL
  931.             && curwin->w_cursor.lnum == Insstart.lnum)
  932.             Insstart_blank_vcol = get_nolist_virtcol();
  933.         }
  934.  
  935.         if (vim_iswordc(c) || !echeck_abbr(c))
  936.         {
  937.         insert_special(c, FALSE, FALSE);
  938.         need_redraw = TRUE;
  939. #ifdef RIGHTLEFT
  940.         revins_legal++;
  941.         revins_chars++;
  942. #endif
  943.         }
  944.         break;
  945.     }   /* end of switch (c) */
  946.  
  947. #ifdef CINDENT
  948.     if (curbuf->b_p_cin && can_cindent
  949. # ifdef INSERT_EXPAND
  950.                         && !ctrl_x_mode
  951. # endif
  952.                                    )
  953.     {
  954. force_cindent:
  955.         /*
  956.          * Indent now if a key was typed that is in 'cinkeys'.
  957.          */
  958.         if (in_cinkeys(c, ' ', line_is_white))
  959.         {
  960.         stop_arrow();
  961.  
  962.         /* re-indent the current line */
  963.         fixthisline(get_c_indent);
  964.  
  965.         /* draw the changes on the screen later */
  966.         need_redraw = TRUE;
  967.         }
  968.     }
  969. #endif /* CINDENT */
  970.  
  971.     }    /* for (;;) */
  972.     /* NOTREACHED */
  973. }
  974.  
  975. /*
  976.  * Put a character directly onto the screen.  It's not stored in a buffer.
  977.  * Used while handling CTRL-K, CTRL-V, etc. in Insert mode.
  978.  */
  979.     static void
  980. edit_putchar(c, highlight)
  981.     int        c;
  982.     int        highlight;
  983. {
  984.     int        attr;
  985.  
  986.     if (NextScreen != NULL)
  987.     {
  988.     update_topline();    /* just in case w_topline isn't valid */
  989.     validate_cursor();
  990.     if (highlight)
  991.         attr = highlight_attr[HLF_8];
  992.     else
  993.         attr = 0;
  994.     screen_putchar(c, curwin->w_winpos + curwin->w_wrow,
  995. #ifdef RIGHTLEFT
  996.             curwin->w_p_rl ? (int)Columns - 1 - curwin->w_wcol :
  997. #endif
  998.                              curwin->w_wcol, attr);
  999.     }
  1000. }
  1001.  
  1002. /*
  1003.  * Called when p_dollar is set: display a '$' at the end of the changed text
  1004.  * Only works when cursor is in the line that changes.
  1005.  */
  1006.     void
  1007. display_dollar(col)
  1008.     colnr_t    col;
  1009. {
  1010.     colnr_t save_col;
  1011.  
  1012.     if (!redrawing())
  1013.     return;
  1014.  
  1015.     cursor_off();
  1016.     save_col = curwin->w_cursor.col;
  1017.     curwin->w_cursor.col = col;
  1018.     curs_columns(FALSE);        /* recompute w_wrow and w_wcol */
  1019.     if (curwin->w_wcol < Columns)
  1020.     {
  1021.     edit_putchar('$', FALSE);
  1022.     dollar_vcol = curwin->w_virtcol;
  1023.     }
  1024.     curwin->w_cursor.col = save_col;
  1025. }
  1026.  
  1027. /*
  1028.  * Call this function before moving the cursor from the normal insert position
  1029.  * in insert mode.
  1030.  */
  1031.     static void
  1032. undisplay_dollar()
  1033. {
  1034.     if (dollar_vcol)
  1035.     {
  1036.     dollar_vcol = 0;
  1037.     update_screenline();
  1038.     }
  1039. }
  1040.  
  1041. /*
  1042.  * Insert an indent (for <Tab> or CTRL-T) or delete an indent (for CTRL-D).
  1043.  * Keep the cursor on the same character.
  1044.  * type == INDENT_INC    increase indent (for CTRL-T or <Tab>)
  1045.  * type == INDENT_DEC    decrease indent (for CTRL-D)
  1046.  * type == INDENT_SET    set indent to "amount"
  1047.  * if round is TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec).
  1048.  */
  1049.     static void
  1050. change_indent(type, amount, round, replaced)
  1051.     int        type;
  1052.     int        amount;
  1053.     int        round;
  1054.     int        replaced;        /* replaced character, put on replace stack */
  1055. {
  1056.     int        vcol;
  1057.     int        last_vcol;
  1058.     int        insstart_less;        /* reduction for Insstart.col */
  1059.     int        new_cursor_col;
  1060.     int        i;
  1061.     char_u    *ptr;
  1062.     int        save_p_list;
  1063.     int        start_col;
  1064.     colnr_t    vc;
  1065.  
  1066.     /* for the following tricks we don't want list mode */
  1067.     save_p_list = curwin->w_p_list;
  1068.     curwin->w_p_list = FALSE;
  1069.     getvcol(curwin, &curwin->w_cursor, NULL, &vc, NULL);
  1070.     vcol = vc;
  1071.  
  1072.     /*
  1073.      * For Replace mode we need to fix the replace stack later, which is only
  1074.      * possible when the cursor is in the indent.  Remember the number of
  1075.      * characters before the cursor if it's possible.
  1076.      */
  1077.     start_col = curwin->w_cursor.col;
  1078.  
  1079.     /* determine offset from first non-blank */
  1080.     new_cursor_col = curwin->w_cursor.col;
  1081.     beginline(BL_WHITE);
  1082.     new_cursor_col -= curwin->w_cursor.col;
  1083.  
  1084.     insstart_less = curwin->w_cursor.col;
  1085.  
  1086.     /*
  1087.      * If the cursor is in the indent, compute how many screen columns the
  1088.      * cursor is to the left of the first non-blank.
  1089.      */
  1090.     if (new_cursor_col < 0)
  1091.     vcol = get_indent() - vcol;
  1092.  
  1093.     if (new_cursor_col > 0)        /* can't fix replace stack */
  1094.     start_col = -1;
  1095.  
  1096.     /*
  1097.      * Set the new indent.  The cursor will be put on the first non-blank.
  1098.      */
  1099.     if (type == INDENT_SET)
  1100.     set_indent(amount, TRUE);
  1101.     else
  1102.     shift_line(type == INDENT_DEC, round, 1);
  1103.     insstart_less -= curwin->w_cursor.col;
  1104.  
  1105.     /*
  1106.      * Try to put cursor on same character.
  1107.      * If the cursor is at or after the first non-blank in the line,
  1108.      * compute the cursor column relative to the column of the first
  1109.      * non-blank character.
  1110.      * If we are not in insert mode, leave the cursor on the first non-blank.
  1111.      * If the cursor is before the first non-blank, position it relative
  1112.      * to the first non-blank, counted in screen columns.
  1113.      */
  1114.     if (new_cursor_col >= 0)
  1115.     new_cursor_col += curwin->w_cursor.col;
  1116.     else if (!(State & INSERT))
  1117.     new_cursor_col = curwin->w_cursor.col;
  1118.     else
  1119.     {
  1120.     /*
  1121.      * Compute the screen column where the cursor should be.
  1122.      */
  1123.     vcol = get_indent() - vcol;
  1124.     curwin->w_virtcol = (vcol < 0) ? 0 : vcol;
  1125.  
  1126.     /*
  1127.      * Advance the cursor until we reach the right screen column.
  1128.      */
  1129.     vcol = last_vcol = 0;
  1130.     new_cursor_col = -1;
  1131.     ptr = ml_get_curline();
  1132.     while (vcol <= (int)curwin->w_virtcol)
  1133.     {
  1134.         last_vcol = vcol;
  1135.         ++new_cursor_col;
  1136.         vcol += lbr_chartabsize(ptr + new_cursor_col, (colnr_t)vcol);
  1137.     }
  1138.     vcol = last_vcol;
  1139.  
  1140.     /*
  1141.      * May need to insert spaces to be able to position the cursor on
  1142.      * the right screen column.
  1143.      */
  1144.     if (vcol != (int)curwin->w_virtcol)
  1145.     {
  1146.         curwin->w_cursor.col = new_cursor_col;
  1147.         i = (int)curwin->w_virtcol - vcol;
  1148.         ptr = alloc(i + 1);
  1149.         if (ptr != NULL)
  1150.         {
  1151.         new_cursor_col += i;
  1152.         ptr[i] = NUL;
  1153.         while (--i >= 0)
  1154.             ptr[i] = ' ';
  1155.         ins_str(ptr);
  1156.         vim_free(ptr);
  1157.         }
  1158.     }
  1159.  
  1160.     /*
  1161.      * When changing the indent while the cursor is in it, reset
  1162.      * Insstart_col to 0.
  1163.      */
  1164.     insstart_less = Insstart.col;
  1165.     }
  1166.  
  1167.     curwin->w_p_list = save_p_list;
  1168.  
  1169.     if (new_cursor_col <= 0)
  1170.     curwin->w_cursor.col = 0;
  1171.     else
  1172.     curwin->w_cursor.col = new_cursor_col;
  1173.     curwin->w_set_curswant = TRUE;
  1174.     changed_cline_bef_curs();
  1175.  
  1176.     /*
  1177.      * May have to adjust the start of the insert.
  1178.      */
  1179.     if ((State & INSERT) && curwin->w_cursor.lnum == Insstart.lnum &&
  1180.                                 Insstart.col != 0)
  1181.     {
  1182.     if ((int)Insstart.col <= insstart_less)
  1183.         Insstart.col = 0;
  1184.     else
  1185.         Insstart.col -= insstart_less;
  1186.     }
  1187.  
  1188.     /*
  1189.      * May have to fix the replace stack, if it's possible.
  1190.      * If the number of characters before the cursor decreased, need to pop a
  1191.      * few characters from the replace stack.
  1192.      * If the number of characters before the cursor increased, need to push a
  1193.      * few NULs onto the replace stack.
  1194.      */
  1195.     if (State == REPLACE && start_col >= 0)
  1196.     {
  1197.     while (start_col > (int)curwin->w_cursor.col)
  1198.     {
  1199.         replace_join(0);        /* remove a NUL from the replace stack */
  1200.         --start_col;
  1201.     }
  1202.     while (start_col < (int)curwin->w_cursor.col || replaced)
  1203.     {
  1204.         replace_push(NUL);
  1205.         if (replaced)
  1206.         {
  1207.         replace_push(replaced);
  1208.         replaced = NUL;
  1209.         }
  1210.         ++start_col;
  1211.     }
  1212.     }
  1213. }
  1214.  
  1215. #ifdef INSERT_EXPAND
  1216. /*
  1217.  * Is the character 'c' a valid key to keep us in the current ctrl-x mode?
  1218.  * -- webb
  1219.  */
  1220.     int
  1221. vim_is_ctrl_x_key(c)
  1222.     int        c;
  1223. {
  1224.     switch (ctrl_x_mode)
  1225.     {
  1226.     case 0:            /* Not in any ctrl-x mode */
  1227.         break;
  1228.     case CTRL_X_NOT_DEFINED_YET:
  1229.         if (       c == Ctrl('X') || c == Ctrl('Y') || c == Ctrl('E')
  1230.             || c == Ctrl('L') || c == Ctrl('F') || c == Ctrl(']')
  1231.             || c == Ctrl('I') || c == Ctrl('D') || c == Ctrl('P')
  1232.             || c == Ctrl('N'))
  1233.         return TRUE;
  1234.         break;
  1235.     case CTRL_X_SCROLL:
  1236.         if (c == Ctrl('Y') || c == Ctrl('E'))
  1237.         return TRUE;
  1238.         break;
  1239.     case CTRL_X_WHOLE_LINE:
  1240.         if (c == Ctrl('L') || c == Ctrl('P') || c == Ctrl('N'))
  1241.         return TRUE;
  1242.         break;
  1243.     case CTRL_X_FILES:
  1244.         if (c == Ctrl('F') || c == Ctrl('P') || c == Ctrl('N'))
  1245.         return TRUE;
  1246.         break;
  1247.     case CTRL_X_DICTIONARY:
  1248.         if (c == Ctrl('K') || c == Ctrl('P') || c == Ctrl('N'))
  1249.         return TRUE;
  1250.         break;
  1251.     case CTRL_X_TAGS:
  1252.         if (c == Ctrl(']') || c == Ctrl('P') || c == Ctrl('N'))
  1253.         return TRUE;
  1254.         break;
  1255. #ifdef FIND_IN_PATH
  1256.     case CTRL_X_PATH_PATTERNS:
  1257.         if (c == Ctrl('P') || c == Ctrl('N'))
  1258.         return TRUE;
  1259.         break;
  1260.     case CTRL_X_PATH_DEFINES:
  1261.         if (c == Ctrl('D') || c == Ctrl('P') || c == Ctrl('N'))
  1262.         return TRUE;
  1263.         break;
  1264. #endif
  1265.     default:
  1266.         emsg(e_internal);
  1267.         break;
  1268.     }
  1269.     return FALSE;
  1270. }
  1271.  
  1272. /*
  1273.  * This is like add_completion(), but if ic and inf are set, then the
  1274.  * case of the originally typed text is used, and the case of the completed
  1275.  * text is infered, ie this tries to work out what case you probably wanted
  1276.  * the rest of the word to be in -- webb
  1277.  */
  1278.     int
  1279. add_completion_and_infercase(str, len, fname, dir, reuse)
  1280.     char_u  *str;
  1281.     int        len;
  1282.     char_u  *fname;
  1283.     int        dir;
  1284.     int     reuse;
  1285. {
  1286.     int has_lower = FALSE;
  1287.     int was_letter = FALSE;
  1288.     int idx;
  1289.  
  1290.     if (p_ic && curbuf->b_p_inf && len < IOSIZE)
  1291.     {
  1292.     /* Infer case of completed part -- webb */
  1293.     /* Use IObuff, str would change text in buffer! */
  1294.     STRNCPY(IObuff, str, len);
  1295.     IObuff[len] = NUL;
  1296.  
  1297.     /* Rule 1: Were any chars converted to lower? */
  1298.     for (idx = 0; idx < completion_length; ++idx)
  1299.     {
  1300.         if (islower(original_text[idx]))
  1301.         {
  1302.         has_lower = TRUE;
  1303.         if (isupper(IObuff[idx]))
  1304.         {
  1305.             /* Rule 1 is satisfied */
  1306.             for (idx = completion_length; idx < len; ++idx)
  1307.             IObuff[idx] = TO_LOWER(IObuff[idx]);
  1308.             break;
  1309.         }
  1310.         }
  1311.     }
  1312.  
  1313.     /*
  1314.      * Rule 2: No lower case, 2nd consecutive letter converted to
  1315.      * upper case.
  1316.      */
  1317.     if (!has_lower)
  1318.     {
  1319.         for (idx = 0; idx < completion_length; ++idx)
  1320.         {
  1321.         if (was_letter && isupper(original_text[idx]) &&
  1322.             islower(IObuff[idx]))
  1323.         {
  1324.             /* Rule 2 is satisfied */
  1325.             for (idx = completion_length; idx < len; ++idx)
  1326.             IObuff[idx] = TO_UPPER(IObuff[idx]);
  1327.             break;
  1328.         }
  1329.         was_letter = isalpha(original_text[idx]);
  1330.         }
  1331.     }
  1332.  
  1333.     /* Copy the original case of the part we typed */
  1334.     STRNCPY(IObuff, original_text, completion_length);
  1335.  
  1336.     return add_completion(IObuff, len, fname, dir, reuse);
  1337.     }
  1338.     return add_completion(str, len, fname, dir, reuse);
  1339. }
  1340.  
  1341. /*
  1342.  * Add a match to the list of matches.
  1343.  * If the given string is already in the list of completions, then return
  1344.  * FAIL, otherwise add it to the list and return OK.  If there is an error,
  1345.  * maybe because alloc returns NULL, then RET_ERROR is returned -- webb.
  1346.  */
  1347.     static int
  1348. add_completion(str, len, fname, dir, reuse)
  1349.     char_u  *str;
  1350.     int        len;
  1351.     char_u  *fname;
  1352.     int        dir;
  1353.     int     reuse;
  1354. {
  1355.     struct Completion *match;
  1356.  
  1357.     ui_breakcheck();
  1358.     if (got_int)
  1359.     return RET_ERROR;
  1360.     if (len < 0)
  1361.     len = STRLEN(str);
  1362.  
  1363.     /*
  1364.      * If the same match is already present, don't add it.
  1365.      */
  1366.     if (first_match != NULL)
  1367.     {
  1368.     match = first_match;
  1369.     do
  1370.     {
  1371.         if (    !(match->original & ORIGINAL_TEXT)
  1372.             && STRNCMP(match->str, str, (size_t)len) == 0
  1373.             && match->str[len] == NUL)
  1374.         return FAIL;
  1375.         match = match->next;
  1376.     } while (match != NULL && match != first_match);
  1377.     }
  1378.  
  1379.     /*
  1380.      * Allocate a new match structure.
  1381.      * Copy the values to the new match structure.
  1382.      */
  1383.     match = (struct Completion *)alloc((unsigned)sizeof(struct Completion));
  1384.     if (match == NULL)
  1385.     return RET_ERROR;
  1386.     if (reuse & ORIGINAL_TEXT)
  1387.     match->str = original_text;
  1388.     else if ((match->str = vim_strnsave(str, len)) == NULL)
  1389.     {
  1390.     vim_free(match);
  1391.     return RET_ERROR;
  1392.     }
  1393.     /* match-fname is:
  1394.      * - curr_match->fname if it is a string equal to fname.
  1395.      * - a copy of fname, FREE_FNAME is set to free later THE allocated mem.
  1396.      * - NULL otherwise.    --Acevedo */
  1397.     if (fname && curr_match && curr_match->fname
  1398.           && STRCMP(fname, curr_match->fname) == 0)
  1399.     match->fname = curr_match->fname;
  1400.     else if (fname && (match->fname = vim_strsave(fname)) != NULL)
  1401.     reuse |= FREE_FNAME;
  1402.     else
  1403.     match->fname = NULL;
  1404.     match->original = reuse;
  1405.  
  1406.     /*
  1407.      * Link the new match structure in the list of matches.
  1408.      */
  1409.     if (first_match == NULL)
  1410.     match->next = match->prev = NULL;
  1411.     else if (dir == FORWARD)
  1412.     {
  1413.     match->next = curr_match->next;
  1414.     match->prev = curr_match;
  1415.     }
  1416.     else    /* BACKWARD */
  1417.     {
  1418.     match->next = curr_match;
  1419.     match->prev = curr_match->prev;
  1420.     }
  1421.     if (match->next)
  1422.     match->next->prev = match;
  1423.     if (match->prev)
  1424.     match->prev->next = match;
  1425.     else    /* if there's nothing before, it is the first match */
  1426.     first_match = match;
  1427.     curr_match = match;
  1428.  
  1429.     return OK;
  1430. }
  1431.  
  1432. /* Make the completion list cyclic.
  1433.  * Return the number of matches (excluding the original).
  1434.  */
  1435.     static int
  1436. make_cyclic()
  1437. {
  1438.     struct Completion *match;
  1439.     int        count = 0;
  1440.  
  1441.     if (first_match != NULL)
  1442.     {
  1443.     /*
  1444.      * Find the end of the list.
  1445.      */
  1446.     match = first_match;
  1447.     /* there's always an entry for the original_text, it doesn't count. */
  1448.     while (match->next != NULL && match->next != first_match)
  1449.     {
  1450.         match = match->next;
  1451.         ++count;
  1452.     }
  1453.     match->next = first_match;
  1454.     first_match->prev = match;
  1455.     }
  1456.     return count;
  1457. }
  1458.  
  1459. #define DICT_FIRST    (1)    /* use just first element in "dict" */
  1460. #define DICT_EXACT    (2)    /* "dict" is the exact name of a file */
  1461. /*
  1462.  * Add any identifiers that match the given pattern to the list of
  1463.  * completions.
  1464.  */
  1465.     static void
  1466. complete_dictionaries(dict, pat, dir, flags)
  1467.     char_u  *dict;
  1468.     char_u  *pat;
  1469.     int         dir;
  1470.     int         flags;
  1471. {
  1472.     char_u    *ptr;
  1473.     char_u    *buf;
  1474.     int        at_start;
  1475.     FILE    *fp;
  1476.     vim_regexp    *prog;
  1477.     int        add_r;
  1478.     char_u    **files;
  1479.     int        count;
  1480.     int        i;
  1481.  
  1482.     buf = alloc(LSIZE);
  1483.     set_reg_ic(pat);    /* set reg_ic according to p_ic, p_scs and pat */
  1484.     prog = vim_regcomp(pat, (int)p_magic);
  1485.     expand_interactively = TRUE;
  1486.     while (buf && prog && *dict != NUL && !got_int)
  1487.     {
  1488.     /* copy one dictionary file name into buf */
  1489.     if (flags == DICT_EXACT)
  1490.     {
  1491.         count = 1;
  1492.         files = &dict;
  1493.     }
  1494.     else
  1495.     {
  1496.         copy_option_part(&dict, buf, LSIZE, ",");
  1497.         if (expand_wildcards(1, &buf, &count, &files, EW_FILE|EW_DIR) != OK)
  1498.         count = 0;
  1499.     }
  1500.  
  1501.     for (i = 0; i < count && !got_int; i++)
  1502.     {
  1503.         fp = fopen((char *)files[i], "r");    /* open dictionary file */
  1504.  
  1505.         if (fp != NULL)
  1506.         {
  1507.         /*
  1508.          * Read dictionary file line by line.
  1509.          * Check each line for a match.
  1510.          */
  1511.         while (!got_int && !vim_fgets(buf, LSIZE, fp))
  1512.         {
  1513.             ptr = buf;
  1514.             at_start = TRUE;
  1515.             while (vim_regexec(prog, ptr, at_start))
  1516.             {
  1517.             at_start = FALSE;
  1518.             ptr = prog->startp[0];
  1519.             while (vim_iswordc(*ptr))
  1520.                 ++ptr;
  1521.             add_r = add_completion_and_infercase(prog->startp[0],
  1522.                 (int)(ptr - prog->startp[0]), files[i], dir, 0);
  1523.             if (add_r == OK)
  1524.                 /* if dir was BACKWARD then honor it just once */
  1525.                 dir = FORWARD;
  1526.             else if (add_r == RET_ERROR)
  1527.                 break;
  1528.             }
  1529.             line_breakcheck();
  1530.         }
  1531.         fclose(fp);
  1532.         }
  1533.     }
  1534.     if (flags != DICT_EXACT && count > 0)
  1535.         FreeWild(count, files);
  1536.     if (flags)
  1537.         break;
  1538.     }
  1539.     expand_interactively = FALSE;
  1540.     vim_free(prog);
  1541.     vim_free(buf);
  1542. }
  1543.  
  1544. /*
  1545.  * Free the list of completions
  1546.  */
  1547.     static void
  1548. free_completions()
  1549. {
  1550.     struct Completion *match;
  1551.  
  1552.     if (first_match == NULL)
  1553.     return;
  1554.     curr_match = first_match;
  1555.     do
  1556.     {
  1557.     match = curr_match;
  1558.     curr_match = curr_match->next;
  1559.     vim_free(match->str);
  1560.     /* several entries may use the same fname, free it just once. */
  1561.     if (match->original & FREE_FNAME)
  1562.         vim_free(match->fname);
  1563.     vim_free(match);
  1564.     } while (curr_match != NULL && curr_match != first_match);
  1565.     first_match = curr_match = NULL;
  1566. }
  1567.  
  1568.     static void
  1569. clear_insexp()
  1570. {
  1571.     continue_status = 0;
  1572.     started_completion = FALSE;
  1573.     complete_pat = NULL;
  1574.     save_sm = -1;
  1575. }
  1576.  
  1577. /*
  1578.  * Prepare for insert-expand, or stop it.
  1579.  */
  1580.     static int
  1581. ins_expand_pre(c)
  1582.     int        c;
  1583. {
  1584.     char_u    *ptr;
  1585.     char_u    *tmp_ptr;
  1586.     int        temp;
  1587.     linenr_t    lnum;
  1588.     int        need_redraw = FALSE;
  1589.  
  1590.     if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET)
  1591.     {
  1592.     /*
  1593.      * We have just entered ctrl-x mode and aren't quite sure which
  1594.      * ctrl-x mode it will be yet.    Now we decide -- webb
  1595.      */
  1596.     switch (c)
  1597.     {
  1598.         case Ctrl('E'):
  1599.         case Ctrl('Y'):
  1600.         ctrl_x_mode = CTRL_X_SCROLL;
  1601.         if (State == INSERT)
  1602.             edit_submode = (char_u *)" (insert) Scroll (^E/^Y)";
  1603.         else
  1604.             edit_submode = (char_u *)" (replace) Scroll (^E/^Y)";
  1605.         showmode();
  1606.         break;
  1607.         case Ctrl('L'):
  1608.         ctrl_x_mode = CTRL_X_WHOLE_LINE;
  1609.         break;
  1610.         case Ctrl('F'):
  1611.         ctrl_x_mode = CTRL_X_FILES;
  1612.         break;
  1613.         case Ctrl('K'):
  1614.         ctrl_x_mode = CTRL_X_DICTIONARY;
  1615.         break;
  1616.         case Ctrl(']'):
  1617.         ctrl_x_mode = CTRL_X_TAGS;
  1618.         break;
  1619. #ifdef FIND_IN_PATH
  1620.         case Ctrl('I'):
  1621.         case K_S_TAB:
  1622.         ctrl_x_mode = CTRL_X_PATH_PATTERNS;
  1623.         break;
  1624.         case Ctrl('D'):
  1625.         ctrl_x_mode = CTRL_X_PATH_DEFINES;
  1626.         break;
  1627. #endif
  1628.         case Ctrl('P'):
  1629.         case Ctrl('N'):
  1630.         /* ^X^P means LOCAL expansion if nothing interrupted (eg we
  1631.          * just started ^X mode, or there were enough ^X's to cancel
  1632.          * the previous mode, say ^X^F^X^X^P or ^P^X^X^X^P, see below)
  1633.          * do normal expansion when interrupting a different mode (say
  1634.          * ^X^F^X^P or ^P^X^X^P, see below)
  1635.          * nothing changes if interrupting mode 0, (eg, the flag
  1636.          * doesn't change when going to ADDING mode  -- Acevedo */
  1637.         if (!(continue_status & CONT_INTRPT))
  1638.             continue_status |= CONT_LOCAL;
  1639.         else if (continue_mode)
  1640.             continue_status &=~CONT_LOCAL;
  1641.         /* FALLTHROUGH */
  1642.         default:
  1643.         /* if we have typed at least 2 ^X's... for modes != 0, we set
  1644.          * continue_status = 0 (eg, as if we had just started ^X mode)
  1645.          * for mode 0, we set continue_mode to an impossible value, in
  1646.          * both cases ^X^X can be used to restart the same mode
  1647.          * (avoiding ADDING mode).   Undocumented feature:
  1648.          * In a mode != 0 ^X^P and ^X^X^P start 'complete' and local
  1649.          * ^P expansions respectively.    In mode 0 an extra ^X is
  1650.          * needed since ^X^P goes to ADDING mode  -- Acevedo */
  1651.         if (c == Ctrl('X'))
  1652.         {
  1653.             if (continue_mode)
  1654.             continue_status = 0;
  1655.             else
  1656.             continue_mode = CTRL_X_NOT_DEFINED_YET;
  1657.         }
  1658.         ctrl_x_mode = 0;
  1659.         edit_submode = NULL;
  1660.         showmode();
  1661.         break;
  1662.     }
  1663.     }
  1664.     else if (ctrl_x_mode)
  1665.     {
  1666.     /* We we're already in ctrl-x mode, do we stay in it? */
  1667.     if (!vim_is_ctrl_x_key(c))
  1668.     {
  1669.         if (ctrl_x_mode == CTRL_X_SCROLL)
  1670.         ctrl_x_mode = 0;
  1671.         else
  1672.         ctrl_x_mode = CTRL_X_FINISHED;
  1673.         edit_submode = NULL;
  1674.     }
  1675.     showmode();
  1676.     }
  1677.     if (started_completion || ctrl_x_mode == CTRL_X_FINISHED)
  1678.     {
  1679.     /* Show error message from attempted keyword completion (probably
  1680.      * 'Pattern not found') until another key is hit, then go back to
  1681.      * showing what mode we are in.
  1682.      */
  1683.     showmode();
  1684.     if ((ctrl_x_mode == 0 && c != Ctrl('N') && c != Ctrl('P')) ||
  1685.                         ctrl_x_mode == CTRL_X_FINISHED)
  1686.     {
  1687.         /* Get here when we have finished typing a sequence of ^N and
  1688.          * ^P or other completion characters in CTRL-X mode. Free up
  1689.          * memory that was used, and make sure we can redo the insert
  1690.          * -- webb.
  1691.          */
  1692.         if (curr_match != NULL)
  1693.         {
  1694.         /*
  1695.          * If any of the original typed text has been changed,
  1696.          * eg when ignorecase is set, we must add back-spaces to
  1697.          * the redo buffer.  We add as few as necessary to delete
  1698.          * just the part of the original text that has changed
  1699.          * -- webb
  1700.          */
  1701.         ptr = curr_match->str;
  1702.         tmp_ptr = original_text;
  1703.         while (*tmp_ptr && *tmp_ptr == *ptr)
  1704.         {
  1705.             ++tmp_ptr;
  1706.             ++ptr;
  1707.         }
  1708.         for (temp = 0; tmp_ptr[temp]; ++temp)
  1709.             AppendCharToRedobuff(K_BS);
  1710.         while (*ptr)
  1711.         {
  1712.             /* Put a string of normal characters in the redo buffer */
  1713.             tmp_ptr = ptr;
  1714.             while (*ptr >= ' ' && *ptr < DEL)
  1715.             ++ptr;
  1716.             /* Don't put '0' or '^' as last character, just in case a
  1717.              * CTRL-D is typed next */
  1718.             if (*ptr == NUL && (ptr[-1] == '0' || ptr[-1] == '^'))
  1719.             --ptr;
  1720.             if (ptr > tmp_ptr)
  1721.             {
  1722.             temp = *ptr;
  1723.             *ptr = NUL;
  1724.             AppendToRedobuff(tmp_ptr);
  1725.             *ptr = temp;
  1726.             }
  1727.             if (*ptr)
  1728.             {
  1729.             /* quote special chars with a CTRL-V */
  1730.             AppendCharToRedobuff(Ctrl('V'));
  1731.             AppendCharToRedobuff(*ptr);
  1732.             /* CTRL-V '0' must be inserted as CTRL-V 048 */
  1733.             if (*ptr++ == '0')
  1734.                 AppendToRedobuff((char_u *)"48");
  1735.             }
  1736.         }
  1737.         }
  1738.         /* Break line if it's too long */
  1739.         lnum = curwin->w_cursor.lnum;
  1740.         /* hmm, we better don't format the WHOLE_LINE just inserted */
  1741.         /* put the cursor on the last char, for correct 'tw' formatting */
  1742.         if (continue_mode != CTRL_X_WHOLE_LINE)
  1743.         {
  1744.         curwin->w_cursor.col--;
  1745.         insertchar(NUL, FALSE, -1, FALSE);
  1746.         curwin->w_cursor.col++;
  1747.         }
  1748.         if (lnum != curwin->w_cursor.lnum)
  1749.         {
  1750.         update_topline();
  1751.         update_screen(NOT_VALID);
  1752.         }
  1753.         else
  1754.         need_redraw = TRUE;
  1755.  
  1756.         vim_free(complete_pat);
  1757.         complete_pat = NULL;
  1758.         free_completions();
  1759.         started_completion = FALSE;
  1760.         ctrl_x_mode = 0;
  1761.         p_sm = save_sm;
  1762.         if (edit_submode != NULL)
  1763.         {
  1764.         edit_submode = NULL;
  1765.         showmode();
  1766.         }
  1767.     }
  1768.     }
  1769.  
  1770.     /* reset continue_* if we left expansion-mode, if we stay they'll be
  1771.      * (re)set properly in ins_complete */
  1772.     if (!ctrl_x_mode && c != Ctrl('P') && c != Ctrl('N') && c != Ctrl('X'))
  1773.     continue_status = continue_mode = 0;
  1774.  
  1775.     return need_redraw;
  1776. }
  1777.  
  1778. /*
  1779.  * Loops through the list of windows, loaded-buffers or non-loaded-buffers
  1780.  * (depending on flag) starting from buf and looking for a non-scanned
  1781.  * buffer (other than curbuf).    curbuf is special, if it is called with
  1782.  * buf=curbuf then it has to be the first call for a given flag/expansion.
  1783.  *
  1784.  * Returns the buffer to scan, if any, otherwise returns curbuf -- Acevedo
  1785.  */
  1786.     static BUF*
  1787. next_buf(buf, flag)
  1788.     BUF        *buf;
  1789.     int        flag;
  1790. {
  1791.     static WIN    *w;
  1792.  
  1793.     if (flag == 'w')        /* just windows */
  1794.     {
  1795.     if (buf == curbuf)    /* first call for this flag/expansion */
  1796.         w = curwin;
  1797.     while ((w = w->w_next ? w->w_next : firstwin) != curwin
  1798.         && w->w_buffer->b_scanned)
  1799.         ;
  1800.     buf = w->w_buffer;
  1801.     }
  1802.     else    /* 'b' (just loaded buffers) or 'u' (just non-loaded buffers) */
  1803.     while ((buf = buf->b_next ? buf->b_next : firstbuf) != curbuf
  1804.         && ((buf->b_ml.ml_mfp == NULL) != (flag == 'u')
  1805.             || buf->b_scanned))
  1806.         ;
  1807.     return buf;
  1808. }
  1809.  
  1810. /*
  1811.  * Get the next expansion(s) for the text starting at the initial curbuf
  1812.  * position "ini" and in the direction dir.
  1813.  * Return the total of matches or -1 if still unknown -- Acevedo
  1814.  */
  1815.     static int
  1816. get_expansion(ini, dir)
  1817.     FPOS    *ini;
  1818.     int        dir;
  1819. {
  1820.     static FPOS        first_match_pos;
  1821.     static FPOS        last_match_pos;
  1822.     static char_u    *e_cpt = (char_u *)"";    /* curr. entry in 'complete' */
  1823.     static int        done_info = 0;    /* Found all matches in this dir. */
  1824.     static BUF        *ins_buf = NULL;
  1825.  
  1826.     FPOS        *pos;
  1827.     char_u        **matches;
  1828.     int            save_p_scs;
  1829.     int            save_p_ws;
  1830.     int            i;
  1831.     int            temp;
  1832.     int            type = ctrl_x_mode;
  1833.     char_u        *ptr;
  1834.     char_u        *tmp_ptr;
  1835.     char_u        *dict = NULL;
  1836.     int            dict_f = 0;
  1837.     struct Completion    *old_match;
  1838.  
  1839.     if (!started_completion)
  1840.     {
  1841.     for (ins_buf = firstbuf; ins_buf; ins_buf = ins_buf->b_next)
  1842.         ins_buf->b_scanned = 0;
  1843.     done_info = 0;
  1844.     ins_buf = curbuf;
  1845.     e_cpt = continue_status & CONT_LOCAL ? (char_u *)"." : curbuf->b_p_cpt;
  1846.     last_match_pos = first_match_pos = *ini;
  1847.     }
  1848.  
  1849.     old_match = curr_match;        /* remember the last current match */
  1850.     pos = (dir == FORWARD) ? &last_match_pos : &first_match_pos;
  1851.     /* For ^N/^P loop over all the flags/windows/buffers in 'complete' */
  1852.     for (;;)
  1853.     {
  1854.     temp = FAIL;
  1855.     /* in mode 0 pick a new entry from e_cpt if started_completion is off,
  1856.      * or if done_info says this entry is done  -- Acevedo */
  1857.     if (!ctrl_x_mode && (!started_completion || done_info == 6))
  1858.     {
  1859.         done_info = 0;
  1860.         while (*e_cpt == ',' || *e_cpt == ' ')
  1861.         e_cpt++;
  1862.         if (*e_cpt == '.' && !curbuf->b_scanned)
  1863.         {
  1864.         ins_buf = curbuf;
  1865.         first_match_pos = *ini;
  1866.         /* So that ^N can match word immediately after cursor */
  1867.         if (ctrl_x_mode == 0)
  1868.             dec(&first_match_pos);
  1869.         last_match_pos = first_match_pos;
  1870.         type = 0;
  1871.         }
  1872.         else if (vim_strchr((char_u *)"buw", *e_cpt) != NULL
  1873.             && (ins_buf = next_buf(ins_buf, *e_cpt)) != curbuf)
  1874.         {
  1875.         if (*e_cpt != 'u')
  1876.         {
  1877.             started_completion = TRUE;
  1878.             first_match_pos.col = last_match_pos.col = 0;
  1879.             first_match_pos.lnum = ins_buf->b_ml.ml_line_count + 1;
  1880.             last_match_pos.lnum = 0;
  1881.             type = 0;
  1882.         }
  1883.         else
  1884.         {
  1885.             done_info = 6;
  1886.             if (ins_buf->b_fname == NULL)
  1887.             continue;
  1888.             type = CTRL_X_DICTIONARY;
  1889.             dict = ins_buf->b_fname;
  1890.             dict_f = DICT_EXACT;
  1891.         }
  1892.         sprintf((char*) IObuff, "Scanning: %s", ins_buf->b_sfname);
  1893.         msg_attr(IObuff, highlight_attr[HLF_R]);
  1894.         }
  1895.         else if (*e_cpt == NUL)
  1896.         break;
  1897.         else
  1898.         {
  1899.         if (*e_cpt == 'k')
  1900.         {
  1901.             type = CTRL_X_DICTIONARY;
  1902.             if (*++e_cpt != ',' && *e_cpt != NUL)
  1903.             {
  1904.             dict = e_cpt;
  1905.             dict_f = DICT_FIRST;
  1906.             }
  1907.         }
  1908. #ifdef FIND_IN_PATH
  1909.         else if (*e_cpt == 'i')
  1910.             type = CTRL_X_PATH_PATTERNS;
  1911. #endif
  1912.         else if (*e_cpt == ']' || *e_cpt == 't')
  1913.             type = CTRL_X_TAGS;
  1914.         else
  1915.             type = -1;
  1916.  
  1917.         /* in any case e_cpt is advanced to the next entry */
  1918.         (void)copy_option_part(&e_cpt, IObuff, IOSIZE, ",");
  1919.  
  1920.         done_info = 6;
  1921.         if (type == -1)
  1922.             continue;
  1923.         }
  1924.     }
  1925.  
  1926.     switch (type)
  1927.     {
  1928.     case -1:
  1929.         break;
  1930. #ifdef FIND_IN_PATH
  1931.     case CTRL_X_PATH_PATTERNS:
  1932.     case CTRL_X_PATH_DEFINES:
  1933.         find_pattern_in_path(complete_pat, dir,
  1934.                  (int)STRLEN(complete_pat), FALSE, FALSE,
  1935.                  (type == CTRL_X_PATH_DEFINES
  1936.                   && !(continue_status & CONT_SOL))
  1937.                  ? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
  1938.                  (linenr_t)1, (linenr_t)MAXLNUM);
  1939.         break;
  1940. #endif
  1941.  
  1942.     case CTRL_X_DICTIONARY:
  1943.         complete_dictionaries(dict ? dict : p_dict, complete_pat, dir,
  1944.                   dict ? dict_f : 0);
  1945.         dict = NULL;
  1946.         break;
  1947.  
  1948.     case CTRL_X_TAGS:
  1949.         /* set reg_ic according to p_ic, p_scs and pat */
  1950.         set_reg_ic(complete_pat);
  1951.         if (find_tags(complete_pat, &temp, &matches,
  1952.                 TAG_REGEXP | TAG_NAMES, MAXCOL) == OK && temp > 0)
  1953.         {
  1954.         int    add_r = OK;
  1955.         int    ldir = dir;
  1956.  
  1957.         for (i = 0; i < temp && add_r != RET_ERROR; i++)
  1958.             if ((add_r = add_completion(matches[i], -1, NULL, ldir, 0))
  1959.                 == OK)
  1960.             /* if dir was BACKWARD then honor it just once */
  1961.             ldir = FORWARD;
  1962.         FreeWild(temp, matches);
  1963.         }
  1964.         break;
  1965.  
  1966.     case CTRL_X_FILES:
  1967.         expand_interactively = TRUE;
  1968.         if (expand_wildcards(1, &complete_pat, &temp, &matches,
  1969.                             EW_FILE|EW_DIR) == OK)
  1970.         {
  1971.         int    add_r = OK;
  1972.         int    ldir = dir;
  1973.  
  1974.         /* May change home directory back to "~". */
  1975.         tilde_replace(complete_pat, temp, matches);
  1976.         for (i = 0; i < temp && add_r != RET_ERROR; i++)
  1977.             if ((add_r = add_completion(matches[i], -1, NULL, ldir, 0))
  1978.                 == OK)
  1979.             /* if dir was BACKWARD then honor it just once */
  1980.             ldir = FORWARD;
  1981.         FreeWild(temp, matches);
  1982.         }
  1983.         expand_interactively = FALSE;
  1984.         break;
  1985.  
  1986.     default:    /* normal ^P/^N and ^X^L */
  1987.         /*
  1988.          * If 'infercase' is set, don't use 'smartcase' here
  1989.          */
  1990.         save_p_scs = p_scs;
  1991.         if (ins_buf->b_p_inf)
  1992.         p_scs = FALSE;
  1993.         /*    buffers other than curbuf are scanned from the beginning or the
  1994.          *    end but never from the middle, thus setting nowrapscan in this
  1995.          *    buffers is a good idea -- Acevedo */
  1996.         save_p_ws = p_ws;
  1997.         if (ins_buf != curbuf)
  1998.         p_ws = FALSE;
  1999.         for (;;)
  2000.         {
  2001.         int    reuse = 0;
  2002.  
  2003.         /* ctrl_x_mode == CTRL_X_WHOLE_LINE || word-wise search that has
  2004.          * added a word that was at the beginning of the line */
  2005.         if (    ctrl_x_mode == CTRL_X_WHOLE_LINE
  2006.             || (continue_status & CONT_SOL))
  2007.             temp = search_for_exact_line(ins_buf, pos,
  2008.                                dir, complete_pat);
  2009.         else
  2010.             temp = searchit(ins_buf, pos, dir, complete_pat, 1L,
  2011.                     SEARCH_KEEP + SEARCH_NFMSG, RE_LAST);
  2012.         if (!started_completion)
  2013.         {
  2014.             /* set started_completion even on fail */
  2015.             started_completion = TRUE;
  2016.             first_match_pos = *pos;
  2017.             last_match_pos = *pos;
  2018.         }
  2019.         else if (first_match_pos.lnum == last_match_pos.lnum
  2020.              && first_match_pos.col == last_match_pos.col)
  2021.             temp = FAIL;
  2022.         if (   temp == FAIL && ins_buf == curbuf
  2023.                && (done_info |= p_ws ? 6 : dir + 3) < 6)
  2024.             /* With nowrapscan, we haven't finished looking in the
  2025.              * other direction yet -- webb */
  2026.             temp = -OK;
  2027.         if (temp != OK)
  2028.             break;
  2029.  
  2030.         /* when ADDING, the text before the cursor matches, skip it */
  2031.         if (    (continue_status & CONT_ADDING) && ins_buf == curbuf
  2032.             && ini->lnum == pos->lnum
  2033.             && ini->col  == pos->col)
  2034.             continue;
  2035.         ptr = ml_get_buf(ins_buf, pos->lnum, FALSE) + pos->col;
  2036.         if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
  2037.         {
  2038.             if (continue_status & CONT_ADDING)
  2039.             {
  2040.             if (pos->lnum >= ins_buf->b_ml.ml_line_count)
  2041.                 continue;
  2042.             ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
  2043.             if (!p_paste)
  2044.                 ptr = skipwhite(ptr);
  2045.             }
  2046.             temp = STRLEN(ptr);
  2047.         }
  2048.         else
  2049.         {
  2050.             tmp_ptr = ptr;
  2051.             if (continue_status & CONT_ADDING)
  2052.             {
  2053.             tmp_ptr += completion_length;
  2054.             if (vim_iswordc(*tmp_ptr))
  2055.                 continue;
  2056.             while (*tmp_ptr && !vim_iswordc(*tmp_ptr++))
  2057.                 ;
  2058.             }
  2059.             while (vim_iswordc(*tmp_ptr))
  2060.             tmp_ptr++;
  2061.             temp = tmp_ptr - ptr;
  2062.             if ((continue_status & CONT_ADDING)
  2063.             && temp == completion_length)
  2064.             {
  2065.             if (pos->lnum < ins_buf->b_ml.ml_line_count)
  2066.             {
  2067.                 /* Try next line, if any. the new word will be "join"
  2068.                  * as if the normal command "J" was used.  IOSIZE is
  2069.                  * always greater than completion_length, so the next
  2070.                  * STRNCPY always works -- Acevedo */
  2071.                 STRNCPY(IObuff, ptr, temp);
  2072.                 ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
  2073.                 tmp_ptr = ptr = skipwhite(ptr);
  2074.                 while (*tmp_ptr && !vim_iswordc(*tmp_ptr++))
  2075.                 ;
  2076.                 while (vim_iswordc(*tmp_ptr))
  2077.                 tmp_ptr++;
  2078.                 if (tmp_ptr > ptr)
  2079.                 {
  2080.                 if (*ptr != ')' && IObuff[temp-1] != TAB)
  2081.                 {
  2082.                     if (IObuff[temp-1] != ' ')
  2083.                     IObuff[temp++] = ' ';
  2084.                     /* IObuf =~ "\k.* ", thus temp >= 2 */
  2085.                     if (p_js
  2086.                     && (IObuff[temp-2] == '.'
  2087.                         || (vim_strchr(p_cpo, CPO_JOINSP)
  2088.                                        == NULL
  2089.                         && (IObuff[temp-2] == '?'
  2090.                             || IObuff[temp-2] == '!'))))
  2091.                     IObuff[temp++] = ' ';
  2092.                 }
  2093.                 /* copy as much as posible of the new word */
  2094.                 if (tmp_ptr - ptr >= IOSIZE - temp)
  2095.                     tmp_ptr = ptr + IOSIZE - temp - 1;
  2096.                 STRNCPY(IObuff + temp, ptr, tmp_ptr - ptr);
  2097.                 temp += tmp_ptr - ptr;
  2098.                 reuse |= CONT_S_IPOS;
  2099.                 }
  2100.                 IObuff[temp] = NUL;
  2101.                 ptr = IObuff;
  2102.             }
  2103.             if (temp == completion_length)
  2104.                 continue;
  2105.             }
  2106.         }
  2107.         if (add_completion_and_infercase(ptr, temp, ins_buf == curbuf ?
  2108.             NULL : ins_buf->b_sfname, dir, reuse) != FAIL)
  2109.         {
  2110.             temp = OK;
  2111.             break;
  2112.         }
  2113.         }
  2114.         p_scs = save_p_scs;
  2115.         p_ws = save_p_ws;
  2116.     }
  2117.     /* check if curr_match has changed, (e.g. other type of expansion
  2118.      * added somenthing) */
  2119.     if (curr_match != old_match)
  2120.         temp = OK;
  2121.     /* break the loop for specialized modes (use 'complete' just for the
  2122.      * generic ctrl_x_mode == 0) and when temp != FAIL */
  2123.     if (ctrl_x_mode || temp)
  2124.         break;
  2125.     if (type == 0 || type == CTRL_X_PATH_PATTERNS)
  2126.         ins_buf->b_scanned = TRUE;
  2127.  
  2128.     started_completion = FALSE;
  2129.     }
  2130.     started_completion = TRUE;
  2131.  
  2132.     i = -1;        /* total of matches, unknown */
  2133.     if (temp == FAIL || (ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE))
  2134.     i = make_cyclic();
  2135.     else if (temp == -OK && (curr_match->original & ORIGINAL_TEXT))
  2136.     {
  2137.     edit_submode_extra = (continue_status & CONT_ADDING)
  2138.         && completion_length > 1
  2139.         ? (dir == FORWARD ? e_hitend_f : e_hitend_b)
  2140.         : (dir == FORWARD ? e_patnotf_f : e_patnotf_b);
  2141.     edit_submode_highl = HLF_E;
  2142.     }
  2143.     /* If several matches were added (FORWARD) or the search failed and has
  2144.      * just been made cyclic then we have to move curr_match to the next or
  2145.      * previous entry (if any, when search failed with 'nows') -- Acevedo */
  2146.     curr_match = dir == FORWARD ? old_match->next : old_match->prev;
  2147.     if (curr_match == NULL)
  2148.     curr_match = old_match;
  2149.     return i;
  2150. }
  2151.  
  2152.     static int
  2153. ins_complete(c)
  2154.     int            c;
  2155. {
  2156.     int            complete_direction;
  2157.     char_u        *ptr;
  2158.     char_u        *tmp_ptr = NULL;        /* init for gcc */
  2159.     static colnr_t  complete_col = 0;        /* init for gcc */
  2160.     int            temp = 0;
  2161.     int            i;
  2162.     int            cc;
  2163.     static FPOS        initial_pos;
  2164.  
  2165.     if (c == Ctrl('P') || c == Ctrl('L'))
  2166.     complete_direction = BACKWARD;
  2167.     else
  2168.     complete_direction = FORWARD;
  2169.     if (!started_completion)
  2170.     {
  2171.     /* First time we hit ^N or ^P (in a row, I mean) */
  2172.  
  2173.     /* Turn off 'sm' so we don't show matches with ^X^L */
  2174.     save_sm = p_sm;
  2175.     p_sm = FALSE;
  2176.  
  2177.     did_ai = FALSE;
  2178. #ifdef SMARTINDENT
  2179.     did_si = FALSE;
  2180.     can_si = FALSE;
  2181.     can_si_back = FALSE;
  2182. #endif
  2183.     stop_arrow();
  2184.     ptr = ml_get(curwin->w_cursor.lnum);
  2185.     complete_col = curwin->w_cursor.col;
  2186.  
  2187.     /* if this same ctrl_x_mode has been interrupted use the text from
  2188.      * initial_pos to the cursor as a pattern to add a new word instead of
  2189.      * expand the one before the cursor, in word-wise if "initial_pos" is
  2190.      * not in the same line as the cursor then fix it (the line has been
  2191.      * split because it was longer than 'tw').  if SOL is set then skip
  2192.      * the previous pattern, a word at the beginning of the line has been
  2193.      * inserted, we'll look for that  -- Acevedo. */
  2194.     if ((continue_status & CONT_INTRPT) && continue_mode == ctrl_x_mode)
  2195.     {    /* it is a continued search */
  2196.         continue_status &= ~CONT_INTRPT;    /* remove INTRPT */
  2197.         if (ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_PATH_PATTERNS
  2198.                     || ctrl_x_mode == CTRL_X_PATH_DEFINES)
  2199.         {
  2200.         if (initial_pos.lnum != curwin->w_cursor.lnum)
  2201.         {
  2202.             /* line (probably) wrapped, set initial_pos to the first
  2203.              * non_blank in the line, if it is not a wordchar include
  2204.              * it to get a better pattern, but then we don't want the
  2205.              * "\\<" prefix, check it bellow */
  2206.             tmp_ptr = skipwhite(ptr);
  2207.             initial_pos.col = tmp_ptr - ptr;
  2208.             initial_pos.lnum = curwin->w_cursor.lnum;
  2209.             continue_status &= ~CONT_SOL;    /* clear SOL if present */
  2210.         }
  2211.         else
  2212.         {
  2213.             /* S_IPOS was set when we inserted a word that was at the
  2214.              * beginning of the line, which means that we'll go to SOL
  2215.              * mode but first we need to redefine initial_pos */
  2216.             if (continue_status & CONT_S_IPOS)
  2217.             {
  2218.             continue_status |= CONT_SOL;
  2219.             initial_pos.col = skipwhite(ptr + completion_length +
  2220.                             initial_pos.col) - ptr;
  2221.             }
  2222.             tmp_ptr = ptr + initial_pos.col;
  2223.         }
  2224.         temp = curwin->w_cursor.col - (tmp_ptr-ptr);
  2225.         /* IObuf is used to add a "word from the next line" would we
  2226.          * have enough space?  just being paranoic */
  2227. #define    MIN_SPACE 75
  2228.         if (temp > (IOSIZE - MIN_SPACE))
  2229.         {
  2230.             continue_status &= ~CONT_SOL;
  2231.             temp = (IOSIZE - MIN_SPACE);
  2232.             tmp_ptr = curwin->w_cursor.col - temp + ptr;
  2233.         }
  2234.         continue_status |= CONT_ADDING | CONT_N_ADDS;
  2235.         if (temp < 1)
  2236.             continue_status &= CONT_LOCAL;
  2237.         }
  2238.         else if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
  2239.         continue_status = CONT_ADDING | CONT_N_ADDS;
  2240.         else
  2241.         continue_status = 0;
  2242.     }
  2243.     else
  2244.         continue_status &= CONT_LOCAL;
  2245.  
  2246.     if (!(continue_status & CONT_ADDING))    /* normal expansion */
  2247.     {
  2248.         continue_mode = ctrl_x_mode;
  2249.         if (ctrl_x_mode)    /* Remove LOCAL iff ctrl_x_mode != 0 */
  2250.         continue_status = 0;
  2251.         continue_status |= CONT_N_ADDS;
  2252.         initial_pos = curwin->w_cursor;
  2253.         temp = (int)complete_col;
  2254.         tmp_ptr = ptr;
  2255.     }
  2256.  
  2257.     /* Work out completion pattern and original text -- webb */
  2258.     if (ctrl_x_mode == 0 || (ctrl_x_mode & CTRL_X_WANT_IDENT))
  2259.     {
  2260.         if (       (continue_status & CONT_SOL)
  2261.             || ctrl_x_mode == CTRL_X_PATH_DEFINES)
  2262.         {
  2263.         if (!(continue_status & CONT_ADDING))
  2264.         {
  2265.             while (--temp >= 0 && vim_isIDc(ptr[temp]))
  2266.             ;
  2267.             tmp_ptr += ++temp;
  2268.             temp = complete_col - temp;
  2269.         }
  2270.         complete_pat = vim_strnsave(tmp_ptr, temp);
  2271.         if (complete_pat == NULL)
  2272.             return FALSE;
  2273.         if (p_ic)
  2274.             for (i = 0; i < temp; i++)
  2275.             complete_pat[i] = TO_LOWER(complete_pat[i]);
  2276.         }
  2277.         else if (continue_status & CONT_ADDING)
  2278.         {
  2279.         char_u        *prefix = (char_u *)"\\<";
  2280.  
  2281.         /* we need 3 extra chars, 1 for the NUL and
  2282.          * 2 >= strlen(prefix)    -- Acevedo */
  2283.         complete_pat = alloc(quote_meta(NULL, tmp_ptr, temp) + 3);
  2284.         if (complete_pat == NULL)
  2285.             return FALSE;
  2286.         if (!vim_iswordc(*tmp_ptr) ||
  2287.             (tmp_ptr > ptr && vim_iswordc(*(tmp_ptr-1))))
  2288.             prefix = (char_u *)"";
  2289.         STRCPY((char *)complete_pat, prefix);
  2290.         (void)quote_meta(complete_pat + STRLEN(prefix), tmp_ptr, temp);
  2291.         }
  2292.         else if (--temp < 0 || !vim_iswordc(ptr[temp]))
  2293.         {
  2294.         /* Match any word of at least two chars */
  2295.         complete_pat = vim_strsave((char_u *)"\\<\\k\\k");
  2296.         if (complete_pat == NULL)
  2297.             return FALSE;
  2298.         tmp_ptr += complete_col;
  2299.         temp = 0;
  2300.         }
  2301.         else
  2302.         {
  2303.         while (--temp >= 0 && vim_iswordc(ptr[temp]))
  2304.             ;
  2305.         tmp_ptr += ++temp;
  2306.         if ((temp = (int)complete_col - temp) == 1)
  2307.         {
  2308.             /* Only match word with at least two chars -- webb
  2309.              * there's no need to call quote_meta,
  2310.              * alloc(7) is enough  -- Acevedo
  2311.              */
  2312.             complete_pat = alloc(7);
  2313.             if (complete_pat == NULL)
  2314.             return FALSE;
  2315.             STRCPY((char *)complete_pat, "\\<");
  2316.             (void)quote_meta(complete_pat + 2, tmp_ptr, 1);
  2317.             STRCAT((char *)complete_pat, "\\k");
  2318.         }
  2319.         else
  2320.         {
  2321.             complete_pat = alloc(quote_meta(NULL, tmp_ptr, temp) + 3);
  2322.             if (complete_pat == NULL)
  2323.             return FALSE;
  2324.             STRCPY((char *)complete_pat, "\\<");
  2325.             (void)quote_meta(complete_pat + 2, tmp_ptr, temp);
  2326.         }
  2327.         }
  2328.     }
  2329.     else if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
  2330.     {
  2331.         tmp_ptr = skipwhite(ptr);
  2332.         temp = (int)complete_col - (tmp_ptr - ptr);
  2333.         complete_pat = vim_strnsave(tmp_ptr, temp);
  2334.         if (complete_pat == NULL)
  2335.         return FALSE;
  2336.         if (p_ic)
  2337.         for (i = 0; i < temp; i ++)
  2338.             complete_pat[i] = TO_LOWER(complete_pat[i]);
  2339.     }
  2340.     else if (ctrl_x_mode == CTRL_X_FILES)
  2341.     {
  2342.         while (--temp >= 0 && vim_isfilec(ptr[temp]))
  2343.         ;
  2344.         tmp_ptr += ++temp;
  2345.         temp = (int)complete_col - temp;
  2346.         complete_pat = addstar(tmp_ptr, temp);
  2347.         if (complete_pat == NULL)
  2348.         return FALSE;
  2349.     }
  2350.     complete_col = tmp_ptr - ptr;
  2351.  
  2352.     if (continue_status & CONT_ADDING)
  2353.     {
  2354.         if (continue_status & CONT_LOCAL)
  2355.         edit_submode = (char_u *)ctrl_x_msgs[2];
  2356.         else
  2357.         edit_submode = (char_u *)ctrl_x_msgs[ctrl_x_mode & 15];
  2358.         if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
  2359.         {
  2360.         /* Insert a new line, keep indentation but ignore 'comments' */
  2361.         char_u *old = curbuf->b_p_com;
  2362.  
  2363.         initial_pos.lnum = curwin->w_cursor.lnum;
  2364.         initial_pos.col = complete_col;
  2365.         curbuf->b_p_com = (char_u *)"";
  2366.         ins_eol('\r');
  2367.         curbuf->b_p_com = old;
  2368.         tmp_ptr = (char_u *)"";
  2369.         temp = 0;
  2370.         complete_col = curwin->w_cursor.col;
  2371.         }
  2372.     }
  2373.     else
  2374.     {
  2375.         /* msg. without the " Adding" part. */
  2376.         if (continue_status & CONT_LOCAL)
  2377.         edit_submode = (char_u *)ctrl_x_msgs[2] + C_X_SKIP;
  2378.         else
  2379.         edit_submode = (char_u *)ctrl_x_msgs[ctrl_x_mode & 15] + C_X_SKIP;
  2380.         initial_pos.col = complete_col;
  2381.     }
  2382.  
  2383.     completion_length = temp;
  2384.     /* Always "add completion" for the "original text", it uses
  2385.      * "original_text" not a copy -- Acevedo */
  2386.     if ((original_text = vim_strnsave(tmp_ptr, temp)) == NULL
  2387.         || add_completion(original_text, -1, NULL, 0, ORIGINAL_TEXT) != OK)
  2388.     {
  2389.         vim_free(complete_pat);
  2390.         complete_pat = NULL;
  2391.         return FALSE;
  2392.     }
  2393.     /* showmode might reset the internal line pointers, so it must
  2394.      * be called before ptr = ml_get, or when this address is no
  2395.      * longer needed.  -- Acevedo.
  2396.      */
  2397.     edit_submode_extra = (char_u *)"-- Searching...";
  2398.     edit_submode_highl = HLF_COUNT;
  2399.     showmode();
  2400.     edit_submode_extra = NULL;
  2401.     out_flush();
  2402.     }
  2403.  
  2404.     /*
  2405.      * In insert mode: Delete the typed part.
  2406.      * In replace mode: Put the old characters back, if any.
  2407.      */
  2408.     i = complete_col + (continue_status & CONT_ADDING ? completion_length : 0);
  2409.     while ((int)curwin->w_cursor.col > i)
  2410.     {
  2411.     curwin->w_cursor.col--;
  2412.     if (State == REPLACE)
  2413.     {
  2414.         /*
  2415.          * First character popped from the replace stack replaces a
  2416.          * character that's already there.    Further popped characters need
  2417.          * to be inserted.
  2418.          */
  2419.         if ((cc = replace_pop()) > 0)
  2420.         {
  2421.         pchar(curwin->w_cursor, cc);
  2422.         replace_pop_ins();
  2423.         }
  2424.     }
  2425.     else
  2426.         (void)del_char(FALSE);
  2427.     }
  2428.     changed_cline_bef_curs();
  2429.     if (complete_direction == FORWARD && curr_match->next != NULL)
  2430.     curr_match = curr_match->next;
  2431.     else if (complete_direction == BACKWARD && curr_match->prev != NULL)
  2432.     curr_match = curr_match->prev;
  2433.     else
  2434.     temp = get_expansion(&initial_pos, complete_direction);
  2435.  
  2436.     /* we found no match if the list has only the original_text-entry */
  2437.     if (first_match == first_match->next)
  2438.     {
  2439.     edit_submode_extra = (continue_status & CONT_ADDING)
  2440.                   && completion_length > 1 ? e_hitend : e_patnotf;
  2441.     edit_submode_highl = HLF_E;
  2442.     /* remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode,
  2443.      * because we couldn't expand anything at first place, but if we used
  2444.      * ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word
  2445.      * (such as M in M'exico) if not tried already.  -- Acevedo */
  2446.     if (       completion_length > 1
  2447.         || (continue_status & CONT_ADDING)
  2448.         || (ctrl_x_mode != 0
  2449.             && ctrl_x_mode != CTRL_X_PATH_PATTERNS
  2450.             && ctrl_x_mode != CTRL_X_PATH_DEFINES))
  2451.         continue_status &= ~CONT_N_ADDS;
  2452.     }
  2453.  
  2454.     /* eat the ESC to avoid leaving insert mode */
  2455.     if (got_int && !global_busy)
  2456.     {
  2457.     (void)vgetc();
  2458.     got_int = FALSE;
  2459.     }
  2460.  
  2461.     if (curr_match->original & CONT_S_IPOS)
  2462.     continue_status |= CONT_S_IPOS;
  2463.     else
  2464.     continue_status &= ~CONT_S_IPOS;
  2465.  
  2466.     if (edit_submode_extra == NULL)
  2467.     {
  2468.     if (curr_match->original & ORIGINAL_TEXT)
  2469.     {
  2470.         edit_submode_extra = (char_u *)"Back at original";
  2471.         edit_submode_highl = HLF_W;
  2472.     }
  2473.     else if (continue_status & CONT_S_IPOS)
  2474.     {
  2475.         edit_submode_extra = (char_u *)"Word from other line";
  2476.         edit_submode_highl = HLF_COUNT;
  2477.     }
  2478.     else if (curr_match->next == curr_match->prev)
  2479.     {
  2480.         edit_submode_extra = (char_u *)"The only match";
  2481.         edit_submode_highl = HLF_COUNT;
  2482.     }
  2483.     }
  2484.  
  2485.     /*
  2486.      * Use ins_char() to insert the text, it is a bit slower than
  2487.      * ins_str(), but it takes care of replace mode.
  2488.      */
  2489.     ptr = curr_match->str + curwin->w_cursor.col - complete_col;
  2490.     while (*ptr)
  2491.     ins_char(*ptr++);
  2492.  
  2493.     update_screenline();
  2494.     if (temp > 1)
  2495.     {
  2496.     if (ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE)
  2497.         ptr = (char_u *)"All %d matches have now been found";
  2498.     else if (ctrl_x_mode == CTRL_X_FILES)
  2499.         ptr = (char_u *)"There are %d matching file names";
  2500.     else if (ctrl_x_mode == CTRL_X_TAGS)
  2501.         ptr = (char_u *)"There are %d matching tags";
  2502.     else
  2503.         ptr = (char_u *)"There are %d matches";
  2504.     sprintf((char *)IObuff, (char *)ptr, temp);
  2505.     if (dollar_vcol)
  2506.         curs_columns(FALSE);
  2507.     msg_attr(IObuff, highlight_attr[HLF_R]);
  2508.     if (!char_avail())
  2509.     {
  2510.         setcursor();
  2511.         out_flush();
  2512.         ui_delay(1500L, FALSE);
  2513.     }
  2514.     }
  2515.     showmode();
  2516.     if (edit_submode_extra != NULL)
  2517.     {
  2518.     if (!p_smd)
  2519.         msg_attr(edit_submode_extra,
  2520.             edit_submode_highl < HLF_COUNT
  2521.             ? highlight_attr[edit_submode_highl] : 0);
  2522.     if (!char_avail())
  2523.     {
  2524.         setcursor();
  2525.         out_flush();
  2526.         ui_delay(1500L, FALSE);
  2527.     }
  2528.     edit_submode_extra = NULL;
  2529.     }
  2530.  
  2531.     /*
  2532.      * Show the file name for the match (if any)
  2533.      * Truncate the file name to avoid a wait for return.
  2534.      */
  2535.     if (curr_match->fname != NULL)
  2536.     {
  2537.     STRCPY(IObuff, "match in file ");
  2538.     i = (vim_strsize(curr_match->fname) + 16) - sc_col;
  2539.     if (i <= 0)
  2540.         i = 0;
  2541.     else
  2542.         STRCAT(IObuff, "<");
  2543.     STRCAT(IObuff, curr_match->fname + i);
  2544.     msg(IObuff);
  2545.     redraw_cmdline = FALSE;        /* don't overwrite! */
  2546.     }
  2547.  
  2548.     return TRUE;
  2549. }
  2550.  
  2551. /*
  2552.  * Looks in the first "len" chars. of "src" for search-metachars.
  2553.  * If dest is not NULL the chars. are copied there quoting (with
  2554.  * a backslash) the metachars, and dest would be NUL terminated.
  2555.  * Returns the length (needed) of dest
  2556.  */
  2557.     static int
  2558. quote_meta(dest, src, len)
  2559.     char_u    *dest;
  2560.     char_u    *src;
  2561.     int        len;
  2562. {
  2563.     int    m;
  2564.  
  2565.     for (m = len; --len >= 0; src++)
  2566.     {
  2567.     switch (*src)
  2568.     {
  2569.         case '.':
  2570.         case '*':
  2571.         case '[':
  2572.         if (ctrl_x_mode == CTRL_X_DICTIONARY)
  2573.             break;
  2574.         case '~':
  2575.         if (!p_magic)    /* quote these only if magic is set */
  2576.             break;
  2577.         case '\\':
  2578.         if (ctrl_x_mode == CTRL_X_DICTIONARY)
  2579.             break;
  2580.         case '^':        /* currently it's not needed. */
  2581.         case '$':
  2582.         m++;
  2583.         if (dest)
  2584.             *dest++ = '\\';
  2585.         break;
  2586.     }
  2587.     if (dest)
  2588.         *dest++ = *src;
  2589.     }
  2590.     if (dest)
  2591.     *dest = NUL;
  2592.  
  2593.     return m;
  2594. }
  2595. #endif /* INSERT_EXPAND */
  2596.  
  2597. /*
  2598.  * Next character is interpreted literally.
  2599.  * A one, two or three digit decimal number is interpreted as its byte value.
  2600.  * If one or two digits are entered, the next character is given to vungetc().
  2601.  */
  2602.     int
  2603. get_literal()
  2604. {
  2605.     int         cc;
  2606.     int         nc;
  2607.     int         i;
  2608.  
  2609.     if (got_int)
  2610.     return Ctrl('C');
  2611.  
  2612. #ifdef USE_GUI
  2613.     /*
  2614.      * In GUI there is no point inserting the internal code for a special key.
  2615.      * It is more useful to insert the string "<KEY>" instead.    This would
  2616.      * probably be useful in a text window too, but it would not be
  2617.      * vi-compatible (maybe there should be an option for it?) -- webb
  2618.      */
  2619.     if (gui.in_use)
  2620.     ++allow_keys;
  2621. #endif
  2622. #ifdef USE_GUI_WIN32
  2623.     dont_scroll = TRUE;        /* disallow scrolling here */
  2624. #endif
  2625.     ++no_mapping;        /* don't map the next key hits */
  2626.     cc = 0;
  2627.     for (i = 0; i < 3; ++i)
  2628.     {
  2629.     do
  2630.         nc = vgetc();
  2631.     while (nc == K_IGNORE || nc == K_SCROLLBAR || nc == K_HORIZ_SCROLLBAR);
  2632. #ifdef SHOWCMD
  2633.     if (!(State & CMDLINE))
  2634.         add_to_showcmd(nc);
  2635. #endif
  2636.     if (!vim_isdigit(nc))
  2637.         break;
  2638.     cc = cc * 10 + nc - '0';
  2639.     if (cc > 255)
  2640.         cc = 255;        /* limit range to 0-255 */
  2641.     nc = 0;
  2642.     }
  2643.     if (i == 0)        /* no number entered */
  2644.     {
  2645.     if (nc == K_ZERO)   /* NUL is stored as NL */
  2646.     {
  2647.         cc = '\n';
  2648.         nc = 0;
  2649.     }
  2650.     else
  2651.     {
  2652.         cc = nc;
  2653.         nc = 0;
  2654.     }
  2655.     }
  2656.  
  2657.     if (cc == 0)    /* NUL is stored as NL */
  2658.     cc = '\n';
  2659.  
  2660.     --no_mapping;
  2661. #ifdef USE_GUI
  2662.     if (gui.in_use)
  2663.     --allow_keys;
  2664. #endif
  2665.     if (nc)
  2666.     vungetc(nc);
  2667.     got_int = FALSE;        /* CTRL-C typed after CTRL-V is not an interrupt */
  2668.     return cc;
  2669. }
  2670.  
  2671. /*
  2672.  * Insert character, taking care of special keys and mod_mask
  2673.  */
  2674.     static void
  2675. insert_special(c, allow_modmask, ctrlv)
  2676.     int        c;
  2677.     int        allow_modmask;
  2678.     int        ctrlv;        /* c was typed after CTRL-V */
  2679. {
  2680.     char_u  *p;
  2681.     int        len;
  2682.  
  2683.     /*
  2684.      * Special function key, translate into "<Key>". Up to the last '>' is
  2685.      * inserted with ins_str(), so as not to replace characters in replace
  2686.      * mode.
  2687.      * Only use mod_mask for special keys, to avoid things like <S-Space>,
  2688.      * unless 'allow_modmask' is TRUE.
  2689.      */
  2690.     if (IS_SPECIAL(c) || (mod_mask && allow_modmask))
  2691.     {
  2692.     p = get_special_key_name(c, mod_mask);
  2693.     len = STRLEN(p);
  2694.     c = p[len - 1];
  2695.     if (len > 2)
  2696.     {
  2697.         p[len - 1] = NUL;
  2698.         ins_str(p);
  2699.         AppendToRedobuff(p);
  2700.         ctrlv = FALSE;
  2701.     }
  2702.     }
  2703.     insertchar(c, FALSE, -1, ctrlv);
  2704. }
  2705.  
  2706. /*
  2707.  * Special characters in this context are those that need processing other
  2708.  * than the simple insertion that can be performed here. This includes ESC
  2709.  * which terminates the insert, and CR/NL which need special processing to
  2710.  * open up a new line. This routine tries to optimize insertions performed by
  2711.  * the "redo", "undo" or "put" commands, so it needs to know when it should
  2712.  * stop and defer processing to the "normal" mechanism.
  2713.  * '0' and '^' are special, because they can be followed by CTRL-D.
  2714.  */
  2715. #define ISSPECIAL(c)    ((c) < ' ' || (c) >= DEL || (c) == '0' || (c) == '^')
  2716.  
  2717.     void
  2718. insertchar(c, force_formatting, second_indent, ctrlv)
  2719.     unsigned    c;
  2720.     int        force_formatting;    /* format line regardless of p_fo */
  2721.     int        second_indent;        /* indent for second line if >= 0 */
  2722.     int        ctrlv;            /* c typed just after CTRL-V */
  2723. {
  2724.     int        haveto_redraw = FALSE;
  2725.     int        textwidth;
  2726.     colnr_t    leader_len;
  2727.     int        first_line = TRUE;
  2728.     int        fo_ins_blank;
  2729.     int        save_char = NUL;
  2730.     int        cc;
  2731.  
  2732.     stop_arrow();
  2733.  
  2734.     textwidth = comp_textwidth(force_formatting);
  2735.     fo_ins_blank = has_format_option(FO_INS_BLANK);
  2736.  
  2737.     /*
  2738.      * Try to break the line in two or more pieces when:
  2739.      * - Always do this if we have been called to do formatting only.
  2740.      * - Otherwise:
  2741.      *     - Don't do this if inserting a blank
  2742.      *     - Don't do this if an existing character is being replaced.
  2743.      *     - Do this if the cursor is not on the line where insert started
  2744.      *     or - 'formatoptions' doesn't have 'l' or the line was not too long
  2745.      *           before the insert.
  2746.      *        - 'formatoptions' doesn't have 'b' or a blank was inserted at or
  2747.      *          before 'textwidth'
  2748.      */
  2749.     if (textwidth
  2750.         && (force_formatting
  2751.         || (!vim_iswhite(c)
  2752.             && !(State == REPLACE && *ml_get_cursor() != NUL)
  2753.             && (curwin->w_cursor.lnum != Insstart.lnum
  2754.             || ((!has_format_option(FO_INS_LONG)
  2755.                 || Insstart_textlen <= (colnr_t)textwidth)
  2756.                 && (!fo_ins_blank
  2757.                 || Insstart_blank_vcol <= (colnr_t)textwidth
  2758.                 ))))))
  2759.     {
  2760.     /*
  2761.      * When 'ai' is off we don't want a space under the cursor to be
  2762.      * deleted.  Replace it with an 'x' temporarily.
  2763.      */
  2764.     if (!curbuf->b_p_ai)
  2765.     {
  2766.         cc = gchar_cursor();
  2767.         if (vim_iswhite(cc))
  2768.         {
  2769.         save_char = cc;
  2770.         pchar_cursor('x');
  2771.         }
  2772.     }
  2773.  
  2774.     /*
  2775.      * Repeat breaking lines, until the current line is not too long.
  2776.      */
  2777.     while (!got_int)
  2778.     {
  2779.         int        startcol;        /* Cursor column at entry */
  2780.         int        wantcol;        /* column at textwidth border */
  2781.         int        foundcol;        /* column for start of spaces */
  2782.         int        end_foundcol = 0;    /* column for start of word */
  2783.         colnr_t    len;
  2784.         colnr_t    virtcol;
  2785.  
  2786.         virtcol = get_nolist_virtcol();
  2787.         if (virtcol < (colnr_t)textwidth)
  2788.         break;
  2789.  
  2790.         if (!force_formatting && has_format_option(FO_WRAP_COMS))
  2791.         fo_do_comments = TRUE;
  2792.  
  2793.         /* Don't break until after the comment leader */
  2794.         leader_len = get_leader_len(ml_get_curline(), NULL);
  2795.         if (!force_formatting && leader_len == 0 &&
  2796.                           !has_format_option(FO_WRAP))
  2797.  
  2798.         {
  2799.         textwidth = 0;
  2800.         break;
  2801.         }
  2802.         if ((startcol = curwin->w_cursor.col) == 0)
  2803.         break;
  2804.                     /* find column of textwidth border */
  2805.         coladvance((colnr_t)textwidth);
  2806.         wantcol = curwin->w_cursor.col;
  2807.  
  2808.         curwin->w_cursor.col = startcol - 1;
  2809.         foundcol = 0;
  2810.         /*
  2811.          * Find position to break at.
  2812.          * Stop at start of line.
  2813.          * Stop at first entered white when 'formatoptions' has 'v'
  2814.          */
  2815.         while (curwin->w_cursor.col > 0 &&
  2816.               ((!fo_ins_blank && !has_format_option(FO_INS_VI)) ||
  2817.                  curwin->w_cursor.lnum != Insstart.lnum ||
  2818.                      curwin->w_cursor.col >= Insstart.col))
  2819.         {
  2820.         cc = gchar_cursor();
  2821.         if (vim_iswhite(cc))
  2822.         {
  2823.             /* remember position of blank just before text */
  2824.             end_foundcol = curwin->w_cursor.col;
  2825.             while (curwin->w_cursor.col > 0 && vim_iswhite(cc))
  2826.             {
  2827.             --curwin->w_cursor.col;
  2828.             cc = gchar_cursor();
  2829.             }
  2830.             if (curwin->w_cursor.col == 0 && vim_iswhite(cc))
  2831.             break;        /* only spaces in front of text */
  2832.             /* Don't break until after the comment leader */
  2833.             if (curwin->w_cursor.col < leader_len)
  2834.             break;
  2835.             foundcol = curwin->w_cursor.col + 1;
  2836.             if (curwin->w_cursor.col < (colnr_t)wantcol)
  2837.             break;
  2838.         }
  2839.         --curwin->w_cursor.col;
  2840.         }
  2841.  
  2842.         if (foundcol == 0)        /* no spaces, cannot break line */
  2843.         {
  2844.         curwin->w_cursor.col = startcol;
  2845.         break;
  2846.         }
  2847.  
  2848.         /*
  2849.          * offset between cursor position and line break is used by
  2850.          * replace stack functions
  2851.          */
  2852.         replace_offset = startcol - end_foundcol - 1;
  2853.  
  2854.         /*
  2855.          * adjust startcol for spaces that will be deleted and
  2856.          * characters that will remain on top line
  2857.          */
  2858.         curwin->w_cursor.col = foundcol;
  2859.         while (cc = gchar_cursor(), vim_iswhite(cc))
  2860.         {
  2861.         ++curwin->w_cursor.col;
  2862.         --startcol;
  2863.         }
  2864.         startcol -= foundcol;
  2865.         if (startcol < 0)
  2866.         startcol = 0;
  2867.  
  2868.         /* put cursor after pos. to break line */
  2869.         curwin->w_cursor.col = foundcol;
  2870.  
  2871.         /*
  2872.          * Split the line before just the margin.
  2873.          * Only insert/delete lines, but don't really redraw the window.
  2874.          */
  2875.         open_line(FORWARD, (redrawing() && !force_formatting) ? -1 : 0,
  2876.                                 TRUE, old_indent);
  2877.         old_indent = 0;
  2878.  
  2879.         replace_offset = 0;
  2880.         if (second_indent >= 0 && first_line)
  2881.         set_indent(second_indent, TRUE);
  2882.         first_line = FALSE;
  2883.  
  2884.         /*
  2885.          * check if cursor is not past the NUL off the line, cindent may
  2886.          * have added or removed indent.
  2887.          */
  2888.         curwin->w_cursor.col += startcol;
  2889.         len = STRLEN(ml_get_curline());
  2890.         if (curwin->w_cursor.col > len)
  2891.         curwin->w_cursor.col = len;
  2892.  
  2893.         haveto_redraw = TRUE;
  2894. #ifdef CINDENT
  2895.         can_cindent = TRUE;
  2896. #endif
  2897.         line_breakcheck();
  2898.     }
  2899.  
  2900.     if (save_char)            /* put back space after cursor */
  2901.         pchar_cursor(save_char);
  2902.  
  2903.     if (c == NUL)            /* formatting only */
  2904.         return;
  2905.     fo_do_comments = FALSE;
  2906.     if (haveto_redraw)
  2907.     {
  2908.         update_topline();
  2909.         update_screen(NOT_VALID);
  2910.     }
  2911.     }
  2912.     if (c == NUL)        /* only formatting was wanted */
  2913.     return;
  2914.  
  2915.     did_ai = FALSE;
  2916. #ifdef SMARTINDENT
  2917.     did_si = FALSE;
  2918.     can_si = FALSE;
  2919.     can_si_back = FALSE;
  2920. #endif
  2921.  
  2922.     /*
  2923.      * If there's any pending input, grab up to INPUT_BUFLEN at once.
  2924.      * This speeds up normal text input considerably.
  2925.      * Don't do this when 'cindent' is set, because we might need to re-indent
  2926.      * at a ':', or any other character.
  2927.      */
  2928. #ifdef USE_GUI_WIN32
  2929.     dont_scroll = FALSE;        /* allow scrolling here */
  2930. #endif
  2931. #define INPUT_BUFLEN 100
  2932.     if (       !ISSPECIAL(c)
  2933.         && vpeekc() != NUL
  2934.         && State != REPLACE
  2935. #ifdef CINDENT
  2936.         && !curbuf->b_p_cin
  2937. #endif
  2938. #ifdef RIGHTLEFT
  2939.         && !p_ri
  2940. #endif
  2941.            )
  2942.     {
  2943.     char_u        p[INPUT_BUFLEN + 1];
  2944.     int        i;
  2945.     colnr_t        virtcol = 0;
  2946.  
  2947.     p[0] = c;
  2948.     i = 1;
  2949.     if (textwidth)
  2950.         virtcol = get_nolist_virtcol();
  2951.     while (       (c = vpeekc()) != NUL
  2952.         && !ISSPECIAL(c)
  2953.         && i < INPUT_BUFLEN
  2954.         && (textwidth == 0
  2955.             || (virtcol += charsize(p[i - 1])) < (colnr_t)textwidth)
  2956.         && !(!no_abbr && !vim_iswordc(c) && vim_iswordc(p[i - 1])))
  2957.     {
  2958. #ifdef RIGHTLEFT
  2959.         c = vgetc();
  2960.         if (p_hkmap && KeyTyped)
  2961.         c = hkmap(c);            /* Hebrew mode mapping */
  2962. #ifdef FKMAP
  2963.         if (p_fkmap && KeyTyped)
  2964.         c = fkmap(c);            /* Farsi mode mapping */
  2965. #endif
  2966.         p[i++] = c;
  2967. #else
  2968.         p[i++] = vgetc();
  2969. #endif
  2970.     }
  2971.  
  2972. #ifdef DIGRAPHS
  2973.     do_digraph(-1);            /* clear digraphs */
  2974.     do_digraph(p[i-1]);        /* may be the start of a digraph */
  2975. #endif
  2976.     p[i] = NUL;
  2977.     ins_str(p);
  2978.     if (ctrlv)
  2979.     {
  2980.         redo_literal(*p);
  2981.         i = 1;
  2982.     }
  2983.     else
  2984.         i = 0;
  2985.     if (p[i] != NUL)
  2986.         AppendToRedobuff(p + i);
  2987.     }
  2988.     else
  2989.     {
  2990.     ins_char(c);
  2991.     if (ctrlv)
  2992.         redo_literal(c);
  2993.     else
  2994.         AppendCharToRedobuff(c);
  2995.     }
  2996. }
  2997.  
  2998. /*
  2999.  * Find out textwidth to be used for formatting:
  3000.  *    if 'textwidth' option is set, use it
  3001.  *    else if 'wrapmargin' option is set, use Columns - 'wrapmargin'
  3002.  *    if invalid value, use 0.
  3003.  *    Set default to window width (maximum 79) for "Q" command.
  3004.  */
  3005.     int
  3006. comp_textwidth(ff)
  3007.     int        ff;    /* force formatting (for "Q" command) */
  3008. {
  3009.     int        textwidth;
  3010.  
  3011.     textwidth = curbuf->b_p_tw;
  3012.     if (textwidth == 0 && curbuf->b_p_wm)
  3013.     textwidth = Columns - curbuf->b_p_wm;
  3014.     if (textwidth < 0)
  3015.     textwidth = 0;
  3016.     if (ff && textwidth == 0)
  3017.     {
  3018.     textwidth = Columns - 1;
  3019.     if (textwidth > 79)
  3020.         textwidth = 79;
  3021.     }
  3022.     return textwidth;
  3023. }
  3024.  
  3025. /*
  3026.  * Put a character in the redo buffer, for when just after a CTRL-V.
  3027.  */
  3028.     static void
  3029. redo_literal(c)
  3030.     int        c;
  3031. {
  3032.     char_u    buf[10];
  3033.  
  3034.     /* Only digits need special treatment.  Translate them into a string of
  3035.      * three digits. */
  3036.     if (vim_isdigit(c))
  3037.     {
  3038.     sprintf((char *)buf, "%03d", c);
  3039.     AppendToRedobuff(buf);
  3040.     }
  3041.     else
  3042.     AppendCharToRedobuff(c);
  3043. }
  3044.  
  3045. /*
  3046.  * start_arrow() is called when an arrow key is used in insert mode.
  3047.  * It resembles hitting the <ESC> key.
  3048.  */
  3049.     static void
  3050. start_arrow(end_insert_pos)
  3051.     FPOS    *end_insert_pos;
  3052. {
  3053.     if (!arrow_used)        /* something has been inserted */
  3054.     {
  3055.     AppendToRedobuff(ESC_STR);
  3056.     arrow_used = TRUE;    /* this means we stopped the current insert */
  3057.     stop_insert(end_insert_pos);
  3058.     }
  3059. }
  3060.  
  3061. /*
  3062.  * stop_arrow() is called before a change is made in insert mode.
  3063.  * If an arrow key has been used, start a new insertion.
  3064.  */
  3065.     void
  3066. stop_arrow()
  3067. {
  3068.     if (arrow_used)
  3069.     {
  3070.     (void)u_save_cursor();            /* errors are ignored! */
  3071.     Insstart = curwin->w_cursor;    /* new insertion starts here */
  3072.     Insstart_textlen = linetabsize(ml_get_curline());
  3073.     ResetRedobuff();
  3074.     AppendToRedobuff((char_u *)"1i");   /* pretend we start an insertion */
  3075.     arrow_used = FALSE;
  3076.     }
  3077. }
  3078.  
  3079. /*
  3080.  * do a few things to stop inserting
  3081.  */
  3082.     static void
  3083. stop_insert(end_insert_pos)
  3084.     FPOS    *end_insert_pos;    /* where insert ended */
  3085. {
  3086.     int        cc;
  3087.  
  3088.     stop_redo_ins();
  3089.     replace_flush();        /* abandon replace stack */
  3090.  
  3091.     /*
  3092.      * save the inserted text for later redo with ^@
  3093.      */
  3094.     vim_free(last_insert);
  3095.     last_insert = get_inserted();
  3096.     last_insert_skip = new_insert_skip;
  3097.  
  3098.     /*
  3099.      * If we just did an auto-indent, remove the white space from the end of
  3100.      * the line, and put the cursor back.
  3101.      */
  3102.     if (did_ai && !arrow_used)
  3103.     {
  3104.     if (gchar_cursor() == NUL && curwin->w_cursor.col > 0)
  3105.         --curwin->w_cursor.col;
  3106.     while (cc = gchar_cursor(), vim_iswhite(cc))
  3107.         (void)del_char(TRUE);
  3108.     if (cc != NUL)
  3109.         ++curwin->w_cursor.col;    /* put cursor back on the NUL */
  3110.     /* the deletion is only seen in list mode and when 'hls' is set */
  3111.     if (curwin->w_p_list || p_hls)
  3112.         update_screenline();
  3113.     }
  3114.     did_ai = FALSE;
  3115. #ifdef SMARTINDENT
  3116.     did_si = FALSE;
  3117.     can_si = FALSE;
  3118.     can_si_back = FALSE;
  3119. #endif
  3120.  
  3121.     /* set '[ and '] to the inserted text */
  3122.     curbuf->b_op_start = Insstart;
  3123.     curbuf->b_op_end = *end_insert_pos;
  3124. }
  3125.  
  3126. /*
  3127.  * Set the last inserted text to a single character.
  3128.  * Used for the replace command.
  3129.  */
  3130.     void
  3131. set_last_insert(c)
  3132.     int        c;
  3133. {
  3134.     vim_free(last_insert);
  3135.     last_insert = alloc(4);
  3136.     if (last_insert != NULL)
  3137.     {
  3138.     last_insert[0] = Ctrl('V');
  3139.     last_insert[1] = c;
  3140.     last_insert[2] = ESC;
  3141.     last_insert[3] = NUL;
  3142.         /* Use the CTRL-V only when not entering a digit */
  3143.     last_insert_skip = isdigit(c) ? 1 : 0;
  3144.     }
  3145. }
  3146.  
  3147. /*
  3148.  * move cursor to start of line
  3149.  * if flags & BL_WHITE    move to first non-white
  3150.  * if flags & BL_SOL    move to first non-white if startofline is set,
  3151.  *                otherwise keep "curswant" column
  3152.  * if flags & BL_FIX    don't leave the cursor on a NUL.
  3153.  */
  3154.     void
  3155. beginline(flags)
  3156.     int        flags;
  3157. {
  3158.     if ((flags & BL_SOL) && !p_sol)
  3159.     coladvance(curwin->w_curswant);
  3160.     else
  3161.     {
  3162.     curwin->w_cursor.col = 0;
  3163.     if (flags & (BL_WHITE | BL_SOL))
  3164.     {
  3165.         char_u  *ptr;
  3166.  
  3167.         for (ptr = ml_get_curline(); vim_iswhite(*ptr)
  3168.                    && !((flags & BL_FIX) && ptr[1] == NUL); ++ptr)
  3169.         ++curwin->w_cursor.col;
  3170.     }
  3171.     curwin->w_set_curswant = TRUE;
  3172.     }
  3173. }
  3174.  
  3175. /*
  3176.  * oneright oneleft cursor_down cursor_up
  3177.  *
  3178.  * Move one char {right,left,down,up}.
  3179.  * Return OK when successful, FAIL when we hit a line of file boundary.
  3180.  */
  3181.  
  3182.     int
  3183. oneright()
  3184. {
  3185.     char_u *ptr;
  3186.  
  3187.     ptr = ml_get_cursor();
  3188.     if (*ptr++ == NUL || *ptr == NUL)
  3189.     return FAIL;
  3190.     curwin->w_set_curswant = TRUE;
  3191.     ++curwin->w_cursor.col;
  3192.     return OK;
  3193. }
  3194.  
  3195.     int
  3196. oneleft()
  3197. {
  3198.     if (curwin->w_cursor.col == 0)
  3199.     return FAIL;
  3200.     curwin->w_set_curswant = TRUE;
  3201.     --curwin->w_cursor.col;
  3202.     return OK;
  3203. }
  3204.  
  3205.     int
  3206. cursor_up(n, upd_topline)
  3207.     long    n;
  3208.     int        upd_topline;        /* When TRUE: update topline */
  3209. {
  3210.     if (n != 0)
  3211.     {
  3212.     if (curwin->w_cursor.lnum <= 1)
  3213.         return FAIL;
  3214.     if (n >= curwin->w_cursor.lnum)
  3215.         curwin->w_cursor.lnum = 1;
  3216.     else
  3217.         curwin->w_cursor.lnum -= n;
  3218.     }
  3219.  
  3220.     /* try to advance to the column we want to be at */
  3221.     coladvance(curwin->w_curswant);
  3222.  
  3223.     if (upd_topline)
  3224.     update_topline();    /* make sure curwin->w_topline is valid */
  3225.  
  3226.     return OK;
  3227. }
  3228.  
  3229.     int
  3230. cursor_down(n, upd_topline)
  3231.     long    n;
  3232.     int        upd_topline;        /* When TRUE: update topline */
  3233. {
  3234.     if (n != 0)
  3235.     {
  3236.     if (curwin->w_cursor.lnum >= curbuf->b_ml.ml_line_count)
  3237.         return FAIL;
  3238.     curwin->w_cursor.lnum += n;
  3239.     if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
  3240.         curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  3241.     }
  3242.  
  3243.     /* try to advance to the column we want to be at */
  3244.     coladvance(curwin->w_curswant);
  3245.  
  3246.     if (upd_topline)
  3247.     update_topline();    /* make sure curwin->w_topline is valid */
  3248.  
  3249.     return OK;
  3250. }
  3251.  
  3252. /*
  3253.  * Stuff the last inserted text in the read buffer.
  3254.  * Last_insert actually is a copy of the redo buffer, so we
  3255.  * first have to remove the command.
  3256.  */
  3257.     int
  3258. stuff_inserted(c, count, no_esc)
  3259.     int        c;        /* Command character to be inserted */
  3260.     long    count;    /* Repeat this many times */
  3261.     int        no_esc;    /* Don't add an ESC at the end */
  3262. {
  3263.     char_u    *esc_ptr;
  3264.     char_u    *ptr;
  3265.     char_u    *last_ptr;
  3266.     char_u    last = NUL;
  3267.  
  3268.     ptr = get_last_insert();
  3269.     if (ptr == NULL)
  3270.     {
  3271.     EMSG(e_noinstext);
  3272.     return FAIL;
  3273.     }
  3274.  
  3275.     /* may want to stuff the command character, to start Insert mode */
  3276.     if (c)
  3277.     stuffcharReadbuff(c);
  3278.     if ((esc_ptr = (char_u *)vim_strrchr(ptr, ESC)) != NULL)
  3279.     *esc_ptr = NUL;        /* remove the ESC */
  3280.  
  3281.     /* when the last char is either "0" or "^" it will be quoted if no ESC
  3282.      * comes after it OR if it will inserted more than once and "ptr"
  3283.      * starts with ^D.    -- Acevedo
  3284.      */
  3285.     last_ptr = (esc_ptr ? esc_ptr : ptr + STRLEN(ptr)) - 1;
  3286.     if (last_ptr >= ptr && (*last_ptr == '0' || *last_ptr == '^')
  3287.         && (no_esc || (*ptr == Ctrl('D') && count > 1)))
  3288.     {
  3289.     last = *last_ptr;
  3290.     *last_ptr = NUL;
  3291.     }
  3292.  
  3293.     do
  3294.     {
  3295.     stuffReadbuff(ptr);
  3296.     /* a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" */
  3297.     if (last)
  3298.         stuffReadbuff((char_u *)(last == '0' ? "\026048" : "\026^"));
  3299.     }
  3300.     while (--count > 0);
  3301.  
  3302.     if (last)
  3303.     *last_ptr = last;
  3304.  
  3305.     if (esc_ptr != NULL)
  3306.     *esc_ptr = ESC;        /* put the ESC back */
  3307.  
  3308.     /* may want to stuff a trailing ESC, to get out of Insert mode */
  3309.     if (!no_esc)
  3310.     stuffcharReadbuff(ESC);
  3311.  
  3312.     return OK;
  3313. }
  3314.  
  3315.     char_u *
  3316. get_last_insert()
  3317. {
  3318.     if (last_insert == NULL)
  3319.     return NULL;
  3320.     return last_insert + last_insert_skip;
  3321. }
  3322.  
  3323. /*
  3324.  * Get last inserted string, and remove trailing <Esc>.
  3325.  * Returns pointer to allocated memory (must be freed) or NULL.
  3326.  */
  3327.     char_u *
  3328. get_last_insert_save()
  3329. {
  3330.     char_u    *s;
  3331.     int        len;
  3332.  
  3333.     if (last_insert == NULL)
  3334.     return NULL;
  3335.     s = vim_strsave(last_insert + last_insert_skip);
  3336.     if (s != NULL)
  3337.     {
  3338.     len = STRLEN(s);
  3339.     if (len > 0 && s[len - 1] == ESC)    /* remove trailing ESC */
  3340.         s[len - 1] = NUL;
  3341.     }
  3342.     return s;
  3343. }
  3344.  
  3345. /*
  3346.  * Check the word in front of the cursor for an abbreviation.
  3347.  * Called when the non-id character "c" has been entered.
  3348.  * When an abbreviation is recognized it is removed from the text and
  3349.  * the replacement string is inserted in typebuf[], followed by "c".
  3350.  */
  3351.     static int
  3352. echeck_abbr(c)
  3353.     int c;
  3354. {
  3355.     if (p_paste || no_abbr)        /* no abbreviations or in paste mode */
  3356.     return FALSE;
  3357.  
  3358.     return check_abbr(c, ml_get_curline(), curwin->w_cursor.col,
  3359.         curwin->w_cursor.lnum == Insstart.lnum ? Insstart.col : 0);
  3360. }
  3361.  
  3362. /*
  3363.  * replace-stack functions
  3364.  *
  3365.  * When replacing characters, the replaced characters are remembered for each
  3366.  * new character.  This is used to re-insert the old text when backspacing.
  3367.  *
  3368.  * There is a NUL headed list of characters for each character that is
  3369.  * currently in the file after the insertion point.  When BS is used, one NUL
  3370.  * headed list is put back for the deleted character.
  3371.  *
  3372.  * For a newline, there are two NUL headed lists.  One contains the characters
  3373.  * that the NL replaced.  The extra one stores the characters after the cursor
  3374.  * that were deleted (always white space).
  3375.  *
  3376.  * Replace_offset is normally 0, in which case replace_push will add a new
  3377.  * character at the end of the stack.  If replace_offset is not 0, that many
  3378.  * characters will be left on the stack above the newly inserted character.
  3379.  */
  3380.  
  3381. char_u    *replace_stack = NULL;
  3382. long    replace_stack_nr = 0;        /* next entry in replace stack */
  3383. long    replace_stack_len = 0;        /* max. number of entries */
  3384.  
  3385.     void
  3386. replace_push(c)
  3387.     int        c;        /* character that is replaced (NUL is none) */
  3388. {
  3389.     char_u  *p;
  3390.  
  3391.     if (replace_stack_nr < replace_offset)    /* nothing to do */
  3392.     return;
  3393.     if (replace_stack_len <= replace_stack_nr)
  3394.     {
  3395.     replace_stack_len += 50;
  3396.     p = lalloc(sizeof(char_u) * replace_stack_len, TRUE);
  3397.     if (p == NULL)        /* out of memory */
  3398.     {
  3399.         replace_stack_len -= 50;
  3400.         return;
  3401.     }
  3402.     if (replace_stack != NULL)
  3403.     {
  3404.         vim_memmove(p, replace_stack,
  3405.                  (size_t)(replace_stack_nr * sizeof(char_u)));
  3406.         vim_free(replace_stack);
  3407.     }
  3408.     replace_stack = p;
  3409.     }
  3410.     p = replace_stack + replace_stack_nr - replace_offset;
  3411.     if (replace_offset)
  3412.     vim_memmove(p + 1, p, (size_t)(replace_offset * sizeof(char_u)));
  3413.     *p = c;
  3414.     ++replace_stack_nr;
  3415. }
  3416.  
  3417. /*
  3418.  * call replace_push(c) with replace_offset set to the first NUL.
  3419.  */
  3420.     static void
  3421. replace_push_off(c)
  3422.     int        c;
  3423. {
  3424.     char_u    *p;
  3425.  
  3426.     p = replace_stack + replace_stack_nr;
  3427.     for (replace_offset = 1; replace_offset < replace_stack_nr;
  3428.                                  ++replace_offset)
  3429.     if (*--p == NUL)
  3430.         break;
  3431.     replace_push(c);
  3432.     replace_offset = 0;
  3433. }
  3434.  
  3435. /*
  3436.  * Pop one item from the replace stack.
  3437.  * return -1 if stack empty
  3438.  * return replaced character or NUL otherwise
  3439.  */
  3440.     static int
  3441. replace_pop()
  3442. {
  3443.     if (replace_stack_nr == 0)
  3444.     return -1;
  3445.     return (int)replace_stack[--replace_stack_nr];
  3446. }
  3447.  
  3448. /*
  3449.  * Join the top two items on the replace stack.  This removes to "off"'th NUL
  3450.  * encountered.
  3451.  */
  3452.     static void
  3453. replace_join(off)
  3454.     int        off;    /* offset for which NUL to remove */
  3455. {
  3456.     int        i;
  3457.  
  3458.     for (i = replace_stack_nr; --i >= 0; )
  3459.     if (replace_stack[i] == NUL && off-- <= 0)
  3460.     {
  3461.         --replace_stack_nr;
  3462.         vim_memmove(replace_stack + i, replace_stack + i + 1,
  3463.                           (size_t)(replace_stack_nr - i));
  3464.         return;
  3465.     }
  3466. }
  3467.  
  3468. /*
  3469.  * Pop characters from the replace stack until a NUL is found, and insert them
  3470.  * before the cursor.  Can only be used in REPLACE mode.
  3471.  */
  3472.     static void
  3473. replace_pop_ins()
  3474. {
  3475.     int        cc;
  3476.  
  3477.     State = NORMAL;            /* don't want REPLACE here */
  3478.     while ((cc = replace_pop()) > 0)
  3479.     {
  3480.     ins_char(cc);
  3481.     dec_cursor();
  3482.     }
  3483.     State = REPLACE;
  3484. }
  3485.  
  3486. /*
  3487.  * make the replace stack empty
  3488.  * (called when exiting replace mode)
  3489.  */
  3490.     static void
  3491. replace_flush()
  3492. {
  3493.     vim_free(replace_stack);
  3494.     replace_stack = NULL;
  3495.     replace_stack_len = 0;
  3496.     replace_stack_nr = 0;
  3497. }
  3498.  
  3499. /*
  3500.  * Handle doing a BS for one character.
  3501.  * cc < 0: replace stack empty, just move cursor
  3502.  * cc == 0: character was inserted, delete it
  3503.  * cc > 0: character was replace, put original back
  3504.  */
  3505.     static void
  3506. replace_do_bs()
  3507. {
  3508.     int        cc;
  3509.  
  3510.     cc = replace_pop();
  3511.     if (cc > 0)
  3512.     {
  3513.     pchar_cursor(cc);
  3514.     replace_pop_ins();
  3515.     }
  3516.     else if (cc == 0)
  3517.     (void)del_char(FALSE);
  3518. }
  3519.  
  3520. #if defined(LISPINDENT) || defined(CINDENT)
  3521. /*
  3522.  * Re-indent the current line, based on the current contents of it and the
  3523.  * surrounding lines. Fixing the cursor position seems really easy -- I'm very
  3524.  * confused what all the part that handles Control-T is doing that I'm not.
  3525.  * "get_the_indent" should be get_c_indent or get_lisp_indent.
  3526.  */
  3527.  
  3528.     void
  3529. fixthisline(get_the_indent)
  3530.     int (*get_the_indent) __ARGS((void));
  3531. {
  3532.     change_indent(INDENT_SET, get_the_indent(), FALSE, 0);
  3533.     if (linewhite(curwin->w_cursor.lnum))
  3534.     did_ai = TRUE;        /* delete the indent if the line stays empty */
  3535. }
  3536. #endif /* defined(LISPINDENT) || defined(CINDENT) */
  3537.  
  3538. #ifdef CINDENT
  3539. /*
  3540.  * return TRUE if 'cinkeys' contains the key "keytyped",
  3541.  * when == '*':        Only if key is preceded with '*'    (indent before insert)
  3542.  * when == '!':        Only if key is prededed with '!'    (don't insert)
  3543.  * when == ' ':        Only if key is not preceded with '*'(indent afterwards)
  3544.  *
  3545.  * If line_is_empty is TRUE accept keys with '0' before them.
  3546.  */
  3547.     int
  3548. in_cinkeys(keytyped, when, line_is_empty)
  3549.     int        keytyped;
  3550.     int        when;
  3551.     int        line_is_empty;
  3552. {
  3553.     char_u  *look;
  3554.     int        try_match;
  3555.     char_u  *p;
  3556.     int        i;
  3557.  
  3558.     for (look = curbuf->b_p_cink; *look; )
  3559.     {
  3560.     /*
  3561.      * Find out if we want to try a match with this key, depending on
  3562.      * 'when' and a '*' or '!' before the key.
  3563.      */
  3564.     switch (when)
  3565.     {
  3566.         case '*': try_match = (*look == '*'); break;
  3567.         case '!': try_match = (*look == '!'); break;
  3568.          default: try_match = (*look != '*'); break;
  3569.     }
  3570.     if (*look == '*' || *look == '!')
  3571.         ++look;
  3572.  
  3573.     /*
  3574.      * If there is a '0', only accept a match if the line is empty.
  3575.      */
  3576.     if (*look == '0')
  3577.     {
  3578.         if (!line_is_empty)
  3579.         try_match = FALSE;
  3580.         ++look;
  3581.     }
  3582.  
  3583.     /*
  3584.      * does it look like a control character?
  3585.      */
  3586.     if (*look == '^' && look[1] >= '@' && look[1] <= '_')
  3587.     {
  3588.         if (try_match && keytyped == Ctrl(look[1]))
  3589.         return TRUE;
  3590.         look += 2;
  3591.     }
  3592.     /*
  3593.      * 'o' means "o" command, open forward.
  3594.      * 'O' means "O" command, open backward.
  3595.      */
  3596.     else if (*look == 'o')
  3597.     {
  3598.         if (try_match && keytyped == KEY_OPEN_FORW)
  3599.         return TRUE;
  3600.         ++look;
  3601.     }
  3602.     else if (*look == 'O')
  3603.     {
  3604.         if (try_match && keytyped == KEY_OPEN_BACK)
  3605.         return TRUE;
  3606.         ++look;
  3607.     }
  3608.  
  3609.     /*
  3610.      * 'e' means to check for "else" at start of line and just before the
  3611.      * cursor.
  3612.      */
  3613.     else if (*look == 'e')
  3614.     {
  3615.         if (try_match && keytyped == 'e' && curwin->w_cursor.col >= 4)
  3616.         {
  3617.         p = ml_get_curline();
  3618.         if (skipwhite(p) == p + curwin->w_cursor.col - 4 &&
  3619.             STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0)
  3620.             return TRUE;
  3621.         }
  3622.         ++look;
  3623.     }
  3624.  
  3625.     /*
  3626.      * ':' only causes an indent if it is at the end of a label or case
  3627.      * statement, or when it was before typing the ':' (to fix
  3628.      * class::method for C++).
  3629.      */
  3630.     else if (*look == ':')
  3631.     {
  3632.         if (try_match && keytyped == ':')
  3633.         {
  3634.         p = ml_get_curline();
  3635.         if (cin_iscase(p) || cin_isscopedecl(p) || cin_islabel(30))
  3636.             return TRUE;
  3637.         if (curwin->w_cursor.col > 2
  3638.             && p[curwin->w_cursor.col - 1] == ':'
  3639.             && p[curwin->w_cursor.col - 2] == ':')
  3640.         {
  3641.             p[curwin->w_cursor.col - 1] = ' ';
  3642.             i = (cin_iscase(p) || cin_isscopedecl(p)
  3643.                               || cin_islabel(30));
  3644.             p = ml_get_curline();
  3645.             p[curwin->w_cursor.col - 1] = ':';
  3646.             if (i)
  3647.             return TRUE;
  3648.         }
  3649.         }
  3650.         ++look;
  3651.     }
  3652.  
  3653.  
  3654.     /*
  3655.      * Is it a key in <>, maybe?
  3656.      */
  3657.     else if (*look == '<')
  3658.     {
  3659.         if (try_match)
  3660.         {
  3661.         /*
  3662.          * make up some named keys <o>, <O>, <e>, <0>, <>>, <<>, <*>
  3663.          * and <!> so that people can re-indent on o, O, e, 0, <, >, *
  3664.          * and ! keys if they really really want to.
  3665.          */
  3666.         if (vim_strchr((char_u *)"<>!*oOe0", look[1]) != NULL &&
  3667.                               keytyped == look[1])
  3668.             return TRUE;
  3669.  
  3670.         if (keytyped == get_special_key_code(look + 1))
  3671.             return TRUE;
  3672.         }
  3673.         while (*look && *look != '>')
  3674.         look++;
  3675.         while (*look == '>')
  3676.         look++;
  3677.     }
  3678.  
  3679.     /*
  3680.      * ok, it's a boring generic character.
  3681.      */
  3682.     else
  3683.     {
  3684.         if (try_match && *look == keytyped)
  3685.         return TRUE;
  3686.         ++look;
  3687.     }
  3688.  
  3689.     /*
  3690.      * Skip over ", ".
  3691.      */
  3692.     look = skip_to_option_part(look);
  3693.     }
  3694.     return FALSE;
  3695. }
  3696. #endif /* CINDENT */
  3697.  
  3698. #if defined(RIGHTLEFT) || defined(PROTO)
  3699. /*
  3700.  * Map Hebrew keyboard when in hkmap mode.
  3701.  */
  3702.     int
  3703. hkmap(c)
  3704.     int c;
  3705. {
  3706.     if (p_hkmapp)   /* phonetic mapping, by Ilya Dogolazky */
  3707.     {
  3708.     enum {hALEF=0, BET, GIMEL, DALET, HEI, VAV, ZAIN, HET, TET, IUD,
  3709.         KAFsofit, hKAF, LAMED, MEMsofit, MEM, NUNsofit, NUN, SAMEH, AIN,
  3710.         PEIsofit, PEI, ZADIsofit, ZADI, KOF, RESH, hSHIN, TAV};
  3711.     static char_u map[26] =
  3712.         {hALEF/*a*/, BET/*b*/, hKAF/*c*/, DALET/*d*/, (char_u)-1/*e*/,
  3713.          PEIsofit/*f*/, GIMEL/*g*/, HEI/*h*/, IUD/*i*/, HET/*j*/, KOF/*k*/,
  3714.          LAMED/*l*/, MEM/*m*/, NUN/*n*/, SAMEH/*o*/, PEI/*p*/,
  3715.          (char_u)-1/*q*/, RESH/*r*/, ZAIN/*s*/, TAV/*t*/, TET/*u*/,
  3716.          VAV/*v*/, hSHIN/*w*/, (char_u)-1/*x*/, AIN/*y*/, ZADI/*z*/};
  3717.  
  3718.     if (c == 'N' || c == 'M' || c == 'P' || c == 'C' || c == 'Z')
  3719.         return map[tolower(c) - 'a'] - 1 + p_aleph; /* '-1'='sofit' */
  3720.     else if (c == 'x')
  3721.         return 'X';
  3722.     else if (c == 'q')
  3723.         return '\''; /* {geresh}={'} */
  3724.     else if (c == 246)
  3725.         return ' ';  /* \"o --> ' ' for a german keyboard */
  3726.     else if (c == 228)
  3727.         return ' ';  /* \"a --> ' '      -- / --           */
  3728.     else if (c == 252)
  3729.         return ' ';  /* \"u --> ' '      -- / --           */
  3730.     else if ('a' <= c && c <= 'z')
  3731.         return map[c - 'a'] + p_aleph;
  3732.     else
  3733.         return c;
  3734.     }
  3735.     else
  3736.     {
  3737.     switch (c)
  3738.     {
  3739.         case '`':    return ';';
  3740.         case '/':    return '.';
  3741.         case '\'':    return ',';
  3742.         case 'q':    return '/';
  3743.         case 'w':    return '\'';
  3744.  
  3745.             /* Hebrew letters - set offset from 'a' */
  3746.         case ',':    c = '{'; break;
  3747.         case '.':    c = 'v'; break;
  3748.         case ';':    c = 't'; break;
  3749.         default: {
  3750.              static char str[] = "zqbcxlsjphmkwonu ydafe rig";
  3751.  
  3752.              if (c < 'a' || c > 'z')
  3753.                  return c;
  3754.              c = str[c - 'a'];
  3755.              break;
  3756.              }
  3757.     }
  3758.  
  3759.     return c - 'a' + p_aleph;
  3760.     }
  3761. }
  3762. #endif
  3763.  
  3764.     static int
  3765. ins_reg()
  3766. {
  3767.     int        need_redraw = FALSE;
  3768.     int        cc;
  3769.     int        literally = FALSE;
  3770.  
  3771.     /*
  3772.      * If we are going to wait for a character, show a '"'.
  3773.      */
  3774.     if (redrawing() && !char_avail())
  3775.     {
  3776.     edit_putchar('"', TRUE);
  3777. #ifdef SHOWCMD
  3778.     add_to_showcmd_c(Ctrl('R'));
  3779. #endif
  3780.     }
  3781.  
  3782. #ifdef USE_GUI_WIN32
  3783.     dont_scroll = TRUE;        /* disallow scrolling here */
  3784. #endif
  3785.  
  3786.     /*
  3787.      * Don't map the register name. This also prevents the mode message to be
  3788.      * deleted when ESC is hit.
  3789.      */
  3790.     ++no_mapping;
  3791.     cc = vgetc();
  3792.     if (cc == Ctrl('R'))
  3793.     {
  3794.     literally = TRUE;
  3795.     cc = vgetc();
  3796.     }
  3797.     --no_mapping;
  3798. #ifdef HAVE_LANGMAP
  3799.     LANGMAP_ADJUST(cc, TRUE);
  3800. #endif
  3801.  
  3802. #ifdef WANT_EVAL
  3803.     /*
  3804.      * Don't call u_sync while getting the expression,
  3805.      * evaluating it or giving an error message for it!
  3806.      */
  3807.     ++no_u_sync;
  3808.     if (cc == '=')
  3809.     cc = get_expr_register();
  3810.     if (cc == NUL)
  3811.     need_redraw = TRUE;    /* remove the '"' */
  3812.     else
  3813.     {
  3814. #endif
  3815.     if (insert_reg(cc, literally) == FAIL)
  3816.     {
  3817.         beep_flush();
  3818.         need_redraw = TRUE;    /* remove the '"' */
  3819.     }
  3820. #ifdef WANT_EVAL
  3821.     }
  3822.     --no_u_sync;
  3823. #endif
  3824. #ifdef SHOWCMD
  3825.     clear_showcmd();
  3826. #endif
  3827.  
  3828.     /* If the inserted register is empty, we need to remove the '"' */
  3829.     if (stuff_empty())
  3830.     need_redraw = TRUE;
  3831.  
  3832.     return need_redraw;
  3833. }
  3834.  
  3835. /*
  3836.  * Handle ESC in insert mode.
  3837.  * Returns TRUE when leaving insert mode, FALSE when going to repeat the
  3838.  * insert.
  3839.  */
  3840.     static int
  3841. ins_esc(count, need_redraw, cmdchar)
  3842.     long    *count;
  3843.     int        need_redraw;
  3844.     int        cmdchar;
  3845. {
  3846.     int         temp;
  3847.     static int     disabled_redraw = FALSE;
  3848.  
  3849.     temp = curwin->w_cursor.col;
  3850.     if (disabled_redraw)
  3851.     {
  3852.     --RedrawingDisabled;
  3853.     disabled_redraw = FALSE;
  3854.     }
  3855.     if (!arrow_used)
  3856.     {
  3857.     /*
  3858.      * Don't append the ESC for "r<CR>".
  3859.      */
  3860.     if (cmdchar != 'r')
  3861.         AppendToRedobuff(ESC_STR);
  3862.  
  3863.     /*
  3864.      * Repeating insert may take a long time.  Check for
  3865.      * interrupt now and then.
  3866.      */
  3867.     if (*count)
  3868.     {
  3869.         line_breakcheck();
  3870.         if (got_int)
  3871.         *count = 0;
  3872.     }
  3873.  
  3874.     if (--*count > 0)    /* repeat what was typed */
  3875.     {
  3876.         (void)start_redo_ins();
  3877.         ++RedrawingDisabled;
  3878.         disabled_redraw = TRUE;
  3879.         return FALSE;    /* repeat the insert */
  3880.     }
  3881.     stop_insert(&curwin->w_cursor);
  3882.     if (dollar_vcol)
  3883.     {
  3884.         dollar_vcol = 0;
  3885.         /* may have to redraw status line if this was the
  3886.          * first change, show "[+]" */
  3887.         if (curwin->w_redr_status == TRUE)
  3888.         redraw_later(NOT_VALID);
  3889.         else
  3890.         need_redraw = TRUE;
  3891.     }
  3892.     }
  3893.     if (need_redraw)
  3894.     update_screenline();
  3895.  
  3896.     /* When an autoindent was removed, curswant stays after the
  3897.      * indent */
  3898.     if (!restart_edit && (colnr_t)temp == curwin->w_cursor.col)
  3899.     curwin->w_set_curswant = TRUE;
  3900.  
  3901.     /*
  3902.      * The cursor should end up on the last inserted character.
  3903.      */
  3904.     if (       curwin->w_cursor.col != 0
  3905.         && (!restart_edit
  3906.         || gchar_cursor() == NUL)
  3907. #ifdef RIGHTLEFT
  3908.         && !revins_on
  3909. #endif
  3910.                       )
  3911.     --curwin->w_cursor.col;
  3912.  
  3913.     /* need to position cursor again (e.g. when on a TAB ) */
  3914.     changed_cline_bef_curs();
  3915.  
  3916.     State = NORMAL;
  3917. #ifdef USE_MOUSE
  3918.     setmouse();
  3919. #endif
  3920. #ifdef USE_GUI
  3921.     if (gui.in_use)
  3922.     gui_upd_cursor_shape();        /* may show different cursor shape */
  3923. #endif
  3924.     /*
  3925.      * When recording or for CTRL-O, need to display the new mode.
  3926.      * Otherwise remove the mode message.
  3927.      */
  3928.     if (Recording || restart_edit)
  3929.     showmode();
  3930.     else if (p_smd)
  3931.     MSG("");
  3932.  
  3933.     return TRUE;        /* exit Insert mode */
  3934. }
  3935.  
  3936. #ifdef RIGHTLEFT
  3937.     static void
  3938. ins_ctrl_()
  3939. {
  3940.     if (revins_on && revins_chars && revins_scol >= 0)
  3941.     {
  3942.     while (gchar_cursor() != NUL && revins_chars--)
  3943.         ++curwin->w_cursor.col;
  3944.     }
  3945.     p_ri = !p_ri;
  3946.     revins_on = (State == INSERT && p_ri);
  3947.     if (revins_on)
  3948.     {
  3949.     revins_scol = curwin->w_cursor.col;
  3950.     revins_legal++;
  3951.     revins_chars = 0;
  3952.     undisplay_dollar();
  3953.     }
  3954.     else
  3955.     revins_scol = -1;
  3956. #ifdef FKMAP
  3957.     if (p_altkeymap)
  3958.     {
  3959.     /*
  3960.      * to be consistent also for redo command, using '.'
  3961.      * set arrow_used to true and stop it - causing to redo
  3962.      * characters entered in one mode (normal/reverse insert).
  3963.      */
  3964.     arrow_used = TRUE;
  3965.     stop_arrow();
  3966.     p_fkmap = curwin->w_p_rl ^ p_ri;
  3967.     if (p_fkmap && p_ri)
  3968.         State = INSERT;
  3969.     }
  3970.     else
  3971. #endif
  3972.     p_hkmap = curwin->w_p_rl ^ p_ri;    /* be consistent! */
  3973.     showmode();
  3974. }
  3975. #endif
  3976.  
  3977. /*
  3978.  * If the cursor is on an indent, ^T/^D insert/delete one
  3979.  * shiftwidth.    Otherwise ^T/^D behave like a "<<" or ">>".
  3980.  * Always round the indent to 'shiftwith', this is compatible
  3981.  * with vi.  But vi only supports ^T and ^D after an
  3982.  * autoindent, we support it everywhere.
  3983.  */
  3984.     static void
  3985. ins_shift(c, lastc)
  3986.     int        c;
  3987.     int        lastc;
  3988. {
  3989.     stop_arrow();
  3990.     AppendCharToRedobuff(c);
  3991.  
  3992.     /*
  3993.      * 0^D and ^^D: remove all indent.
  3994.      */
  3995.     if ((lastc == '0' || lastc == '^') && curwin->w_cursor.col)
  3996.     {
  3997.     --curwin->w_cursor.col;
  3998.     (void)del_char(FALSE);        /* delete the '^' or '0' */
  3999.     /* In Replace mode, restore the characters that '^' or '0' replaced. */
  4000.     if (State == REPLACE)
  4001.         replace_pop_ins();
  4002.     if (lastc == '^')
  4003.         old_indent = get_indent();    /* remember curr. indent */
  4004.     change_indent(INDENT_SET, 0, TRUE, 0);
  4005.     }
  4006.     else
  4007.     change_indent(c == Ctrl('D') ? INDENT_DEC : INDENT_INC, 0, TRUE, 0);
  4008.  
  4009.     did_ai = FALSE;
  4010. #ifdef SMARTINDENT
  4011.     did_si = FALSE;
  4012.     can_si = FALSE;
  4013.     can_si_back = FALSE;
  4014. #endif
  4015. #ifdef CINDENT
  4016.     can_cindent = FALSE;    /* no cindenting after ^D or ^T */
  4017. #endif
  4018. }
  4019.  
  4020.     static void
  4021. ins_del()
  4022. {
  4023.     int        temp;
  4024.  
  4025.     stop_arrow();
  4026.     if (gchar_cursor() == NUL)        /* delete newline */
  4027.     {
  4028.     temp = curwin->w_cursor.col;
  4029.     if (!p_bs ||            /* only if 'bs' set */
  4030.         u_save((linenr_t)(curwin->w_cursor.lnum - 1),
  4031.         (linenr_t)(curwin->w_cursor.lnum + 2)) == FAIL ||
  4032.             do_join(FALSE, TRUE) == FAIL)
  4033.         beep_flush();
  4034.     else
  4035.     {
  4036.         curwin->w_cursor.col = temp;
  4037.         redraw_later(VALID_TO_CURSCHAR);
  4038.     }
  4039.     }
  4040.     else if (del_char(FALSE) == FAIL)/* delete char under cursor */
  4041.     beep_flush();
  4042.     did_ai = FALSE;
  4043. #ifdef SMARTINDENT
  4044.     did_si = FALSE;
  4045.     can_si = FALSE;
  4046.     can_si_back = FALSE;
  4047. #endif
  4048.     AppendCharToRedobuff(K_DEL);
  4049. }
  4050.  
  4051. /*
  4052.  * Handle Backspace, delete-word and delete-line in Insert mode.
  4053.  * Return TRUE when backspace was actually used.
  4054.  */
  4055.     static int
  4056. ins_bs(c, mode, inserted_space_p)
  4057.     int        c;
  4058.     int        mode;
  4059.     int        *inserted_space_p;
  4060. {
  4061.     linenr_t    lnum;
  4062.     int        cc;
  4063.     int        temp = 0;        /* init for GCC */
  4064.     colnr_t    mincol;
  4065.     int        did_backspace = FALSE;
  4066.     int        in_indent;
  4067.  
  4068.     /*
  4069.      * can't delete anything in an empty file
  4070.      * can't backup past first character in buffer
  4071.      * can't backup past starting point unless 'backspace' > 1
  4072.      * can backup to a previous line if 'backspace' == 0
  4073.      */
  4074.     if (       bufempty()
  4075.         || (
  4076. #ifdef RIGHTLEFT
  4077.         !revins_on &&
  4078. #endif
  4079.         ((curwin->w_cursor.lnum == 1 && curwin->w_cursor.col <= 0)
  4080.             || (p_bs < 2
  4081.             && (arrow_used
  4082.                 || (curwin->w_cursor.lnum == Insstart.lnum
  4083.                 && curwin->w_cursor.col <= Insstart.col)
  4084.                 || (curwin->w_cursor.col <= 0 && p_bs == 0))))))
  4085.     {
  4086.     beep_flush();
  4087.     return FALSE;
  4088.     }
  4089.  
  4090.     stop_arrow();
  4091.     in_indent = inindent(0);
  4092. #ifdef CINDENT
  4093.     if (in_indent)
  4094.     can_cindent = FALSE;
  4095. #endif
  4096. #ifdef RIGHTLEFT
  4097.     if (revins_on)        /* put cursor after last inserted char */
  4098.     inc_cursor();
  4099. #endif
  4100.  
  4101.     /*
  4102.      * delete newline!
  4103.      */
  4104.     if (curwin->w_cursor.col <= 0)
  4105.     {
  4106.     lnum = Insstart.lnum;
  4107.     if (curwin->w_cursor.lnum == Insstart.lnum
  4108. #ifdef RIGHTLEFT
  4109.             || revins_on
  4110. #endif
  4111.                     )
  4112.     {
  4113.         if (u_save((linenr_t)(curwin->w_cursor.lnum - 2),
  4114.                    (linenr_t)(curwin->w_cursor.lnum + 1)) == FAIL)
  4115.         return FALSE;
  4116.         --Insstart.lnum;
  4117.         Insstart.col = 0;
  4118.     }
  4119.     /*
  4120.      * In replace mode:
  4121.      * cc < 0: NL was inserted, delete it
  4122.      * cc >= 0: NL was replaced, put original characters back
  4123.      */
  4124.     cc = -1;
  4125.     if (State == REPLACE)
  4126.         cc = replace_pop();        /* returns -1 if NL was inserted */
  4127.     /*
  4128.      * In replace mode, in the line we started replacing, we only move the
  4129.      * cursor.
  4130.      */
  4131.     if (State != REPLACE || curwin->w_cursor.lnum > lnum)
  4132.     {
  4133.         temp = gchar_cursor();    /* remember current char */
  4134.         --curwin->w_cursor.lnum;
  4135.         (void)do_join(FALSE, TRUE);
  4136.         redraw_later(VALID_TO_CURSCHAR);
  4137.         if (temp == NUL && gchar_cursor() != NUL)
  4138.         ++curwin->w_cursor.col;
  4139.         /*
  4140.          * In REPLACE mode we have to put back the text that was replace
  4141.          * by the NL. On the replace stack is first a NUL-terminated
  4142.          * sequence of characters that were deleted and then the
  4143.          * characters that NL replaced.
  4144.          */
  4145.         if (State == REPLACE)
  4146.         {
  4147.         /*
  4148.          * Do the next ins_char() in NORMAL state, to
  4149.          * prevent ins_char() from replacing characters and
  4150.          * avoiding showmatch().
  4151.          */
  4152.         State = NORMAL;
  4153.         /*
  4154.          * restore characters (blanks) deleted after cursor
  4155.          */
  4156.         while (cc > 0)
  4157.         {
  4158.             temp = curwin->w_cursor.col;
  4159.             ins_char(cc);
  4160.             curwin->w_cursor.col = temp;
  4161.             cc = replace_pop();
  4162.         }
  4163.         /* restore the characters that NL replaced */
  4164.         replace_pop_ins();    /* will set State back to REPLACE */
  4165.         }
  4166.     }
  4167.     else
  4168.         dec_cursor();
  4169.     did_ai = FALSE;
  4170.     }
  4171.     else
  4172.     {
  4173.     /*
  4174.      * Delete character(s) before the cursor.
  4175.      */
  4176. #ifdef RIGHTLEFT
  4177.     if (revins_on)        /* put cursor on last inserted char */
  4178.         dec_cursor();
  4179. #endif
  4180.     mincol = 0;
  4181.                         /* keep indent */
  4182.     if (mode == BACKSPACE_LINE && curbuf->b_p_ai
  4183. #ifdef RIGHTLEFT
  4184.         && !revins_on
  4185. #endif
  4186.                 )
  4187.     {
  4188.         temp = curwin->w_cursor.col;
  4189.         beginline(BL_WHITE);
  4190.         if (curwin->w_cursor.col < (colnr_t)temp)
  4191.         mincol = curwin->w_cursor.col;
  4192.         curwin->w_cursor.col = temp;
  4193.     }
  4194.  
  4195.     /*
  4196.      * Handle deleting one 'shiftwidth' or 'softtabstop'.
  4197.      */
  4198.     if (       mode == BACKSPACE_CHAR
  4199.         && ((p_sta && in_indent)
  4200.             || (curbuf->b_p_sts
  4201.             && (*(ml_get_cursor() - 1) == TAB
  4202.                 || (*(ml_get_cursor() - 1) == ' '
  4203.                 && (!*inserted_space_p
  4204.                     || arrow_used))))))
  4205.     {
  4206.         int        ts;
  4207.         colnr_t    vcol;
  4208.         int        want_vcol;
  4209.         int        extra = 0;
  4210.  
  4211.         *inserted_space_p = FALSE;
  4212.         if (p_sta)
  4213.         ts = curbuf->b_p_sw;
  4214.         else
  4215.         ts = curbuf->b_p_sts;
  4216.         /* compute the virtual column where we want to be */
  4217.         getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
  4218.         want_vcol = ((vcol - 1) / ts) * ts;
  4219.         /* delete characters until we are at or before want_vcol */
  4220.         while ((int)vcol > want_vcol
  4221.             && (cc = *(ml_get_cursor() - 1), vim_iswhite(cc)))
  4222.         {
  4223.         dec_cursor();
  4224.         /* TODO: calling getvcol() each time is slow */
  4225.         getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
  4226.         if (State == REPLACE)
  4227.         {
  4228.             /* don't delete characters before the insert point when in
  4229.              * Replace mode */
  4230.             if (curwin->w_cursor.lnum != Insstart.lnum
  4231.                 || curwin->w_cursor.col >= Insstart.col)
  4232.             {
  4233.             if ((int)vcol < want_vcol)
  4234.             {
  4235.                 (void)del_char(FALSE);
  4236.                 extra = 2;    /* don't pop too much */
  4237.             }
  4238.             else
  4239.                 replace_do_bs();
  4240.             }
  4241.         }
  4242.         else
  4243.             (void)del_char(FALSE);
  4244.         }
  4245.         /* insert extra spaces until we are at want_vcol */
  4246.         while ((int)vcol < want_vcol)
  4247.         {
  4248.         ins_str((char_u *)" ");
  4249.         if (State == REPLACE && extra <= 1)
  4250.         {
  4251.             if (extra)
  4252.             replace_push_off(NUL);
  4253.             else
  4254.             replace_push(NUL);
  4255.         }
  4256.         getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
  4257.         if (extra == 2)
  4258.             extra = 1;
  4259.         }
  4260.     }
  4261.  
  4262.     /*
  4263.      * Delete upto starting point, start of line or previous word.
  4264.      */
  4265.     else do
  4266.     {
  4267. #ifdef RIGHTLEFT
  4268.         if (!revins_on) /* put cursor on char to be deleted */
  4269. #endif
  4270.         dec_cursor();
  4271.  
  4272.         /* start of word? */
  4273.         if (mode == BACKSPACE_WORD && !vim_isspace(gchar_cursor()))
  4274.         {
  4275.         mode = BACKSPACE_WORD_NOT_SPACE;
  4276.         temp = vim_iswordc(gchar_cursor());
  4277.         }
  4278.         /* end of word? */
  4279.         else if (mode == BACKSPACE_WORD_NOT_SPACE
  4280.             && (vim_isspace(cc = gchar_cursor())
  4281.                 || vim_iswordc(cc) != temp))
  4282.         {
  4283. #ifdef RIGHTLEFT
  4284.         if (!revins_on)
  4285. #endif
  4286.             inc_cursor();
  4287. #ifdef RIGHTLEFT
  4288.         else if (State == REPLACE)
  4289.             dec_cursor();
  4290. #endif
  4291.         break;
  4292.         }
  4293.         if (State == REPLACE)
  4294.         replace_do_bs();
  4295.         else  /* State != REPLACE */
  4296.         {
  4297.         (void)del_char(FALSE);
  4298. #ifdef RIGHTLEFT
  4299.         if (revins_chars)
  4300.         {
  4301.             revins_chars--;
  4302.             revins_legal++;
  4303.         }
  4304.         if (revins_on && gchar_cursor() == NUL)
  4305.             break;
  4306. #endif
  4307.         }
  4308.         /* Just a single backspace?: */
  4309.         if (mode == BACKSPACE_CHAR)
  4310.         break;
  4311.     } while (
  4312. #ifdef RIGHTLEFT
  4313.         revins_on ||
  4314. #endif
  4315.         (curwin->w_cursor.col > mincol &&
  4316.         (curwin->w_cursor.lnum != Insstart.lnum ||
  4317.         curwin->w_cursor.col != Insstart.col)));
  4318.     did_backspace = TRUE;
  4319.     }
  4320. #ifdef SMARTINDENT
  4321.     did_si = FALSE;
  4322.     can_si = FALSE;
  4323.     can_si_back = FALSE;
  4324. #endif
  4325.     if (curwin->w_cursor.col <= 1)
  4326.     did_ai = FALSE;
  4327.     /*
  4328.      * It's a little strange to put backspaces into the redo
  4329.      * buffer, but it makes auto-indent a lot easier to deal
  4330.      * with.
  4331.      */
  4332.     AppendCharToRedobuff(c);
  4333.  
  4334.     /* If deleted before the insertion point, adjust it */
  4335.     if (curwin->w_cursor.lnum == Insstart.lnum
  4336.                        && curwin->w_cursor.col < Insstart.col)
  4337.     Insstart.col = curwin->w_cursor.col;
  4338.  
  4339.     return did_backspace;
  4340. }
  4341.  
  4342. #ifdef USE_MOUSE
  4343.     static void
  4344. ins_mouse(c)
  4345.     int        c;
  4346. {
  4347.     FPOS    tpos;
  4348.  
  4349. # ifdef USE_GUI
  4350.     /* When GUI is active, also move/paste when 'mouse' is empty */
  4351.     if (!gui.in_use)
  4352. # endif
  4353.     if (!mouse_has(MOUSE_INSERT))
  4354.         return;
  4355.  
  4356.     undisplay_dollar();
  4357.     tpos = curwin->w_cursor;
  4358.     if (do_mouse(NULL, c, BACKWARD, 1L, FALSE))
  4359.     {
  4360.     start_arrow(&tpos);
  4361. # ifdef CINDENT
  4362.     can_cindent = TRUE;
  4363. # endif
  4364.     }
  4365. }
  4366. #endif
  4367.  
  4368. #ifdef USE_GUI
  4369.     void
  4370. ins_scroll()
  4371. {
  4372.     FPOS    tpos;
  4373.  
  4374.     undisplay_dollar();
  4375.     tpos = curwin->w_cursor;
  4376.     if (gui_do_scroll())
  4377.     {
  4378.     start_arrow(&tpos);
  4379. # ifdef CINDENT
  4380.     can_cindent = TRUE;
  4381. # endif
  4382.     }
  4383. }
  4384.  
  4385.     void
  4386. ins_horscroll()
  4387. {
  4388.     FPOS    tpos;
  4389.  
  4390.     undisplay_dollar();
  4391.     tpos = curwin->w_cursor;
  4392.     if (gui_do_horiz_scroll())
  4393.     {
  4394.     start_arrow(&tpos);
  4395. #ifdef CINDENT
  4396.     can_cindent = TRUE;
  4397. #endif
  4398.     }
  4399. }
  4400. #endif
  4401.  
  4402.     static void
  4403. ins_left()
  4404. {
  4405.     FPOS    tpos;
  4406.  
  4407.     undisplay_dollar();
  4408.     tpos = curwin->w_cursor;
  4409.     if (oneleft() == OK)
  4410.     {
  4411.     start_arrow(&tpos);
  4412. #ifdef RIGHTLEFT
  4413.     /* If exit reversed string, position is fixed */
  4414.     if (revins_scol != -1 && (int)curwin->w_cursor.col >= revins_scol)
  4415.         revins_legal++;
  4416.     revins_chars++;
  4417. #endif
  4418.     }
  4419.  
  4420.     /*
  4421.      * if 'whichwrap' set for cursor in insert mode may go to
  4422.      * previous line
  4423.      */
  4424.     else if (vim_strchr(p_ww, '[') != NULL && curwin->w_cursor.lnum > 1)
  4425.     {
  4426.     start_arrow(&tpos);
  4427.     --(curwin->w_cursor.lnum);
  4428.     coladvance(MAXCOL);
  4429.     curwin->w_set_curswant = TRUE;    /* so we stay at the end */
  4430.     }
  4431.     else
  4432.     beep_flush();
  4433. }
  4434.  
  4435.     static void
  4436. ins_home()
  4437. {
  4438.     FPOS    tpos;
  4439.  
  4440.     undisplay_dollar();
  4441.     tpos = curwin->w_cursor;
  4442.     if ((mod_mask & MOD_MASK_CTRL))
  4443.     curwin->w_cursor.lnum = 1;
  4444.     curwin->w_cursor.col = 0;
  4445.     curwin->w_curswant = 0;
  4446.     start_arrow(&tpos);
  4447. }
  4448.  
  4449.     static void
  4450. ins_end()
  4451. {
  4452.     FPOS    tpos;
  4453.  
  4454.     undisplay_dollar();
  4455.     tpos = curwin->w_cursor;
  4456.     if ((mod_mask & MOD_MASK_CTRL))
  4457.     curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  4458.     coladvance(MAXCOL);
  4459.     curwin->w_curswant = MAXCOL;
  4460.     start_arrow(&tpos);
  4461. }
  4462.  
  4463.     static void
  4464. ins_s_left()
  4465. {
  4466.     undisplay_dollar();
  4467.     if (curwin->w_cursor.lnum > 1 || curwin->w_cursor.col > 0)
  4468.     {
  4469.     start_arrow(&curwin->w_cursor);
  4470.     (void)bck_word(1L, 0, FALSE);
  4471.     }
  4472.     else
  4473.     beep_flush();
  4474. }
  4475.  
  4476.     static void
  4477. ins_right()
  4478. {
  4479.     undisplay_dollar();
  4480.     if (gchar_cursor() != NUL)
  4481.     {
  4482.     start_arrow(&curwin->w_cursor);
  4483.     curwin->w_set_curswant = TRUE;
  4484.     ++curwin->w_cursor.col;
  4485. #ifdef RIGHTLEFT
  4486.     revins_legal++;
  4487.     if (revins_chars)
  4488.         revins_chars--;
  4489. #endif
  4490.     }
  4491.     /* if 'whichwrap' set for cursor in insert mode, may move the
  4492.      * cursor to the next line */
  4493.     else if (vim_strchr(p_ww, ']') != NULL
  4494.         && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
  4495.     {
  4496.     start_arrow(&curwin->w_cursor);
  4497.     curwin->w_set_curswant = TRUE;
  4498.     ++curwin->w_cursor.lnum;
  4499.     curwin->w_cursor.col = 0;
  4500.     }
  4501.     else
  4502.     beep_flush();
  4503. }
  4504.  
  4505.     static void
  4506. ins_s_right()
  4507. {
  4508.     undisplay_dollar();
  4509.     if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count
  4510.         || gchar_cursor() != NUL)
  4511.     {
  4512.     start_arrow(&curwin->w_cursor);
  4513.     (void)fwd_word(1L, 0, 0);
  4514.     }
  4515.     else
  4516.     beep_flush();
  4517. }
  4518.  
  4519.     static void
  4520. ins_up()
  4521. {
  4522.     FPOS    tpos;
  4523.     linenr_t    old_topline;
  4524.  
  4525.     undisplay_dollar();
  4526.     tpos = curwin->w_cursor;
  4527.     old_topline = curwin->w_topline;
  4528.     if (cursor_up(1L, TRUE) == OK)
  4529.     {
  4530.     if (old_topline != curwin->w_topline)
  4531.         update_screen(VALID);
  4532.     start_arrow(&tpos);
  4533. #ifdef CINDENT
  4534.     can_cindent = TRUE;
  4535. #endif
  4536.     }
  4537.     else
  4538.     beep_flush();
  4539. }
  4540.  
  4541.     static void
  4542. ins_pageup()
  4543. {
  4544.     FPOS    tpos;
  4545.  
  4546.     undisplay_dollar();
  4547.     tpos = curwin->w_cursor;
  4548.     if (onepage(BACKWARD, 1L) == OK)
  4549.     {
  4550.     start_arrow(&tpos);
  4551. #ifdef CINDENT
  4552.     can_cindent = TRUE;
  4553. #endif
  4554.     }
  4555.     else
  4556.     beep_flush();
  4557. }
  4558.  
  4559.     static void
  4560. ins_down()
  4561. {
  4562.     FPOS    tpos;
  4563.     linenr_t    old_topline = curwin->w_topline;
  4564.  
  4565.     undisplay_dollar();
  4566.     tpos = curwin->w_cursor;
  4567.     if (cursor_down(1L, TRUE) == OK)
  4568.     {
  4569.     if (old_topline != curwin->w_topline)
  4570.         update_screen(VALID);
  4571.     start_arrow(&tpos);
  4572. #ifdef CINDENT
  4573.     can_cindent = TRUE;
  4574. #endif
  4575.     }
  4576.     else
  4577.     beep_flush();
  4578. }
  4579.  
  4580.     static void
  4581. ins_pagedown()
  4582. {
  4583.     FPOS    tpos;
  4584.  
  4585.     undisplay_dollar();
  4586.     tpos = curwin->w_cursor;
  4587.     if (onepage(FORWARD, 1L) == OK)
  4588.     {
  4589.     start_arrow(&tpos);
  4590. #ifdef CINDENT
  4591.     can_cindent = TRUE;
  4592. #endif
  4593.     }
  4594.     else
  4595.     beep_flush();
  4596. }
  4597.  
  4598. /*
  4599.  * Handle TAB in Insert or Replace mode.
  4600.  * Return TRUE when the TAB needs to be inserted like a normal character.
  4601.  */
  4602.     static int
  4603. ins_tab()
  4604. {
  4605.     int        i;
  4606.     int        temp;
  4607.  
  4608.     if (Insstart_blank_vcol == MAXCOL && curwin->w_cursor.lnum == Insstart.lnum)
  4609.     Insstart_blank_vcol = get_nolist_virtcol();
  4610.     if (echeck_abbr(TAB + ABBR_OFF))
  4611.     return FALSE;
  4612.  
  4613.     i = inindent(0);
  4614. #ifdef CINDENT
  4615.     if (i)
  4616.     can_cindent = FALSE;
  4617. #endif
  4618.  
  4619.     /*
  4620.      * When nothing special, insert TAB like a normal character
  4621.      */
  4622.     if (!curbuf->b_p_et && !(p_sta && i) && !curbuf->b_p_sts)
  4623.     return TRUE;
  4624.  
  4625.     stop_arrow();
  4626.     did_ai = FALSE;
  4627. #ifdef SMARTINDENT
  4628.     did_si = FALSE;
  4629.     can_si = FALSE;
  4630.     can_si_back = FALSE;
  4631. #endif
  4632.     AppendToRedobuff((char_u *)"\t");
  4633.  
  4634.     if (p_sta && i)            /* insert tab in indent */
  4635.     {
  4636.     if (State == REPLACE)        /* delete a char first */
  4637.     {
  4638.         i = gchar_cursor();
  4639.         if (i)
  4640.         del_char(FALSE);
  4641.     }
  4642.     change_indent(INDENT_INC, 0, TRUE, i);
  4643.     return FALSE;
  4644.     }
  4645.  
  4646.     /*
  4647.      * p_et or p_sts is set: expand a tab into spaces
  4648.      */
  4649.     if (curbuf->b_p_sts)
  4650.     temp = (int)curbuf->b_p_sts;
  4651.     else
  4652.     temp = (int)curbuf->b_p_ts;
  4653.     temp -= get_nolist_virtcol() % temp;
  4654.  
  4655.     /*
  4656.      * Insert the first space with ins_char().    It will delete one char in
  4657.      * replace mode.  Insert the rest with ins_str(); it will not delete any
  4658.      * chars.
  4659.      */
  4660.     ins_char(' ');
  4661.     while (--temp)
  4662.     {
  4663.     ins_str((char_u *)" ");
  4664.     if (State == REPLACE)        /* no char replaced */
  4665.         replace_push(NUL);
  4666.     }
  4667.  
  4668.     /*
  4669.      * For 'softtabstop': Replace a number of spaces by a TAB, if possible.
  4670.      */
  4671.     if (curbuf->b_p_sts && !curbuf->b_p_et)
  4672.     {
  4673.     char_u        *ptr;
  4674.     FPOS        fpos;
  4675.     colnr_t        want_vcol, vcol, tab_vcol;
  4676.     int        did_change = FALSE;
  4677.     int        ts = curbuf->b_p_ts;
  4678.  
  4679.     /* find first white before the cursor */
  4680.     ptr = ml_get_cursor();
  4681.     fpos = curwin->w_cursor;
  4682.     while (fpos.col > 0 && vim_iswhite(ptr[-1]))
  4683.     {
  4684.         --fpos.col;
  4685.         --ptr;
  4686.     }
  4687.  
  4688.     /* In Replace mode, don't change characters before the insert point. */
  4689.     if (State == REPLACE && fpos.lnum == Insstart.lnum
  4690.                            && fpos.col < Insstart.col)
  4691.     {
  4692.         ptr += Insstart.col - fpos.col;
  4693.         fpos.col = Insstart.col;
  4694.     }
  4695.  
  4696.     /* compute virtual column numbers of first white and cursor */
  4697.     getvcol(curwin, &fpos, &vcol, NULL, NULL);
  4698.     getvcol(curwin, &curwin->w_cursor, &want_vcol, NULL, NULL);
  4699.  
  4700.     /* use as many TABs as possible */
  4701.     tab_vcol = (want_vcol / ts) * ts;
  4702.     while (vcol < tab_vcol)
  4703.     {
  4704.         if (*ptr != TAB)
  4705.         {
  4706.         *ptr = TAB;
  4707.         did_change = TRUE;
  4708.         }
  4709.         ++fpos.col;
  4710.         ++ptr;
  4711.         vcol = ((vcol + ts) / ts) * ts;
  4712.     }
  4713.  
  4714.     if (did_change)
  4715.     {
  4716.         /* may need to delete a number of the following spaces */
  4717.         i = want_vcol - vcol;
  4718.         ptr += i;
  4719.         fpos.col += i;
  4720.         i = curwin->w_cursor.col - fpos.col;
  4721.         if (i > 0)
  4722.         {
  4723.         vim_memmove(ptr, ptr + i, STRLEN(ptr + i) + 1);
  4724.         /* correct replace stack. */
  4725.         if (State == REPLACE)
  4726.             for (temp = i; --temp >= 0; )
  4727.             replace_join(want_vcol - vcol);
  4728.         }
  4729.         curwin->w_cursor.col -= i;
  4730.     }
  4731.     }
  4732.  
  4733.     return FALSE;
  4734. }
  4735.  
  4736. /*
  4737.  * Handle CR or NL in insert mode.
  4738.  * Return TRUE when out of memory.
  4739.  */
  4740.     static int
  4741. ins_eol(c)
  4742.     int        c;
  4743. {
  4744.     int        i;
  4745.  
  4746.     if (echeck_abbr(c + ABBR_OFF))
  4747.     return FALSE;
  4748.     stop_arrow();
  4749.     /*
  4750.      * Strange Vi behaviour: In Replace mode, typing a NL will not delete the
  4751.      * character under the cursor.  Only push a NUL on the replace stack,
  4752.      * nothing to put back when the NL is deleted.
  4753.      */
  4754.     if (State == REPLACE)
  4755.     replace_push(NUL);
  4756. #ifdef RIGHTLEFT
  4757. # ifdef FKMAP
  4758.     if (p_altkeymap && p_fkmap)
  4759.     fkmap(NL);
  4760. # endif
  4761.     /* NL in reverse insert will allways start in the end of
  4762.      * current line. */
  4763.     if (revins_on)
  4764.     while (gchar_cursor() != NUL)
  4765.         ++curwin->w_cursor.col;
  4766. #endif
  4767.  
  4768.     AppendToRedobuff(NL_STR);
  4769.     if (has_format_option(FO_RET_COMS))
  4770.     fo_do_comments = TRUE;
  4771.     i = open_line(FORWARD, TRUE, FALSE, old_indent);
  4772.     old_indent = 0;
  4773.     fo_do_comments = FALSE;
  4774. #ifdef CINDENT
  4775.     can_cindent = TRUE;
  4776. #endif
  4777.  
  4778.     return (!i);
  4779. }
  4780.  
  4781. #ifdef DIGRAPHS
  4782. /*
  4783.  * Handle digraph in insert mode.
  4784.  * Returns character still to be inserted, or NUL when nothing remaining to be
  4785.  * done.
  4786.  */
  4787.     static int
  4788. ins_digraph()
  4789. {
  4790.     int        c;
  4791.     int        cc;
  4792.  
  4793.     if (redrawing() && !char_avail())
  4794.     {
  4795.     edit_putchar('?', TRUE);
  4796. #ifdef SHOWCMD
  4797.     add_to_showcmd_c(Ctrl('K'));
  4798. #endif
  4799.     }
  4800.  
  4801. #ifdef USE_GUI_WIN32
  4802.     dont_scroll = TRUE;        /* disallow scrolling here */
  4803. #endif
  4804.  
  4805.     /* don't map the digraph chars. This also prevents the
  4806.      * mode message to be deleted when ESC is hit */
  4807.     ++no_mapping;
  4808.     ++allow_keys;
  4809.     c = vgetc();
  4810.     --no_mapping;
  4811.     --allow_keys;
  4812.     if (IS_SPECIAL(c))        /* special key */
  4813.     {
  4814. #ifdef SHOWCMD
  4815.     clear_showcmd();
  4816. #endif
  4817.     insert_special(c, TRUE, FALSE);
  4818.     return NUL;
  4819.     }
  4820.     if (c != ESC)
  4821.     {
  4822.     if (redrawing() && !char_avail())
  4823.     {
  4824.         if (charsize(c) == 1)
  4825.         edit_putchar(c, TRUE);
  4826. #ifdef SHOWCMD
  4827.         add_to_showcmd_c(c);
  4828. #endif
  4829.     }
  4830.     ++no_mapping;
  4831.     ++allow_keys;
  4832.     cc = vgetc();
  4833.     --no_mapping;
  4834.     --allow_keys;
  4835.     if (cc != ESC)
  4836.     {
  4837.         AppendToRedobuff((char_u *)"\026");    /* CTRL-V */
  4838.         c = getdigraph(c, cc, TRUE);
  4839. #ifdef SHOWCMD
  4840.         clear_showcmd();
  4841. #endif
  4842.         return c;
  4843.     }
  4844.     }
  4845. #ifdef SHOWCMD
  4846.     clear_showcmd();
  4847. #endif
  4848.     return NUL;
  4849. }
  4850. #endif
  4851.  
  4852. /*
  4853.  * Handle CTRL-E and CTRL-Y in Insert mode: copy char from other line.
  4854.  * Returns the char to be inserted, or NUL if none found.
  4855.  */
  4856.     static int
  4857. ins_copychar(lnum)
  4858.     linenr_t    lnum;
  4859. {
  4860.     int        c;
  4861.     int        temp;
  4862.     char_u  *ptr;
  4863.  
  4864.     if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
  4865.     {
  4866.     beep_flush();
  4867.     return NUL;
  4868.     }
  4869.  
  4870.     /* try to advance to the cursor column */
  4871.     temp = 0;
  4872.     ptr = ml_get(lnum);
  4873.     validate_virtcol();
  4874.     while ((colnr_t)temp < curwin->w_virtcol && *ptr)
  4875.     temp += lbr_chartabsize(ptr++, (colnr_t)temp);
  4876.  
  4877.     if ((colnr_t)temp > curwin->w_virtcol)
  4878.     --ptr;
  4879.     if ((c = *ptr) == NUL)
  4880.     beep_flush();
  4881.     return c;
  4882. }
  4883.  
  4884. #ifdef SMARTINDENT
  4885. /*
  4886.  * Try to do some very smart auto-indenting.
  4887.  * Used when inserting a "normal" character.
  4888.  */
  4889.     static void
  4890. ins_try_si(c)
  4891.     int        c;
  4892. {
  4893.     FPOS    *pos, old_pos;
  4894.     char_u    *ptr;
  4895.     int        i;
  4896.     int        temp;
  4897.  
  4898.     /*
  4899.      * do some very smart indenting when entering '{' or '}'
  4900.      */
  4901.     if (((did_si || can_si_back) && c == '{') || (can_si && c == '}'))
  4902.     {
  4903.     /*
  4904.      * for '}' set indent equal to indent of line containing matching '{'
  4905.      */
  4906.     if (c == '}' && (pos = findmatch(NULL, '{')) != NULL)
  4907.     {
  4908.         old_pos = curwin->w_cursor;
  4909.         /*
  4910.          * If the matching '{' has a ')' immediately before it (ignoring
  4911.          * white-space), then line up with the start of the line
  4912.          * containing the matching '(' if there is one.  This handles the
  4913.          * case where an "if (..\n..) {" statement continues over multiple
  4914.          * lines -- webb
  4915.          */
  4916.         ptr = ml_get(pos->lnum);
  4917.         i = pos->col;
  4918.         if (i > 0)        /* skip blanks before '{' */
  4919.         while (--i > 0 && vim_iswhite(ptr[i]))
  4920.             ;
  4921.         curwin->w_cursor.lnum = pos->lnum;
  4922.         curwin->w_cursor.col = i;
  4923.         if (ptr[i] == ')' && (pos = findmatch(NULL, '(')) != NULL)
  4924.         curwin->w_cursor = *pos;
  4925.         i = get_indent();
  4926.         curwin->w_cursor = old_pos;
  4927.         set_indent(i, TRUE);
  4928.     }
  4929.     else if (curwin->w_cursor.col > 0)
  4930.     {
  4931.         /*
  4932.          * when inserting '{' after "O" reduce indent, but not
  4933.          * more than indent of previous line
  4934.          */
  4935.         temp = TRUE;
  4936.         if (c == '{' && can_si_back && curwin->w_cursor.lnum > 1)
  4937.         {
  4938.         old_pos = curwin->w_cursor;
  4939.         i = get_indent();
  4940.         while (curwin->w_cursor.lnum > 1)
  4941.         {
  4942.             ptr = skipwhite(ml_get(--(curwin->w_cursor.lnum)));
  4943.             /* ignore empty lines and lines starting with
  4944.              * '#'.
  4945.              */
  4946.             if (*ptr != '#' && *ptr != NUL)
  4947.             break;
  4948.         }
  4949.         if (get_indent() >= i)
  4950.             temp = FALSE;
  4951.         curwin->w_cursor = old_pos;
  4952.         }
  4953.         if (temp)
  4954.         shift_line(TRUE, FALSE, 1);
  4955.     }
  4956.     }
  4957.  
  4958.     /*
  4959.      * set indent of '#' always to 0
  4960.      */
  4961.     if (curwin->w_cursor.col > 0 && can_si && c == '#')
  4962.     {
  4963.     /* remember current indent for next line */
  4964.     old_indent = get_indent();
  4965.     set_indent(0, TRUE);
  4966.     }
  4967. }
  4968. #endif
  4969.  
  4970. /*
  4971.  * Get the value that w_virtcol would have when 'list' is off.
  4972.  * Unless 'cpo' contains the 'L' flag.
  4973.  */
  4974.     static colnr_t
  4975. get_nolist_virtcol()
  4976. {
  4977.     colnr_t    virtcol;
  4978.  
  4979.     if (curwin->w_p_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL)
  4980.     {
  4981.     curwin->w_p_list = FALSE;
  4982.     getvcol(curwin, &curwin->w_cursor, NULL, &virtcol, NULL);
  4983.     curwin->w_p_list = TRUE;
  4984.     return virtcol;
  4985.     }
  4986.     validate_virtcol();
  4987.     return curwin->w_virtcol;
  4988. }
  4989.